Added $376 setting for designating ABC-axes individually as rotational.

Added `$ESG` and `$ESH` system commands for outputting current setting definitions.
Added setting descriptions to most settings. Work in progress.
Added/updated preprocessor code for leaner board map files++
This commit is contained in:
Terje Io
2021-08-20 18:53:20 +02:00
parent 6f5d1cd31c
commit 384fda6e3a
17 changed files with 787 additions and 271 deletions
+2 -1
View File
@@ -11,7 +11,8 @@ It has been written to complement grblHAL and has features such as proper keyboa
---
Latest build date is 20210803, see the [changelog](changelog.md) for details.
Latest build date is 20210819, 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.
---
+16
View File
@@ -1,5 +1,21 @@
## grblHAL changelog
Build 20210819:
Core:
* Added `$376` setting for designating ABC-axes individually as rotational.
__NOTE:__ This setting is only available when N_AXIS is > 3 and will force a settings reset on an upgrade for such configurations. Backup and restore settings when upgrading!
Scaling from inches to mm is disabled for axes designated as rotational, no other processing takes place.
* Added `$ESG` and `$ESH` system commands for outputting current setting definitions in [Grbl csv-format](https://github.com/gnea/grbl/tree/master/doc/csv) and grblHAL tab-format respectively.
Only settings valid in the active configuration will be outputted, driver and plugin specific settings will be added as well - even from well behaved third party code.
* Added setting descriptions to most core/driver/plugin settings. Third party drivers and plugins may also add descriptions to any settings implementented.
NOTE: Drivers for processors with limited flash may not have the descriptions compiled in.
* Added `$SED=<n>` for outputting a description for setting `<n>` (if available), e.g. issue `$SED=14` to get a description for `$14`. The description is formatted for sender use.
Drivers & plugins:
* Cleaned up/simplified many pin mapping files, mostly by moving pin to bit transforms to a common preprocessor file.
* Some general driver and plugin improvements, e.g. more flexible spindle PWM to pin mappings for STM32F4xx and STM32F7xx drivers.
Build 20210803:
Core:
+6
View File
@@ -400,6 +400,12 @@ __NOTE:__ these definitions are only referenced in this file. Do __NOT__ change!
//#define DEFAULT_STEPPING_INVERT_MASK 0
//#define DEFAULT_DIRECTION_INVERT_MASK 0
// Designate ABC axes as rotational. This will disable scaling (to mm) in inches mode.
// Set steps/mm for the axes to the value that represent the desired movement per unit.
// For the controller the distance is unitless and and can be in degrees, radians, rotations, ...
// NOTE: $376 can be used to configure rotational axes at run-time.
//#define ST_ROTATIONAL_MASK (A_AXIS_BIT|B_AXIS_BIT|C_AXIS_BIT) // Default disabled. Uncomment and possibly remove axis bit(s) as needed to enable.
// Inverts logic of the input signals based on a mask. This essentially means you are using
// normally-open (NO) switches on the specified pins, rather than the default normally-closed (NC) switches.
// NOTE: The first option will invert all control pins. The second option is an example of
+4
View File
@@ -557,6 +557,10 @@
#define ST_DEENERGIZE_MASK 0
#endif
#ifndef ST_ROTATIONAL_MASK
#define ST_ROTATIONAL_MASK 0
#endif
#ifndef INVERT_ST_ENABLE_MASK
#define INVERT_ST_ENABLE_MASK 0
#endif
+6
View File
@@ -141,6 +141,12 @@
#define LIMITS_OVERRIDE_ENABLE 0
#endif
#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
#define SAFETY_DOOR_ENABLE 1
#else
#define SAFETY_DOOR_ENABLE 0
#endif
#ifndef ESTOP_ENABLE
#if COMPATIBILITY_LEVEL <= 1
#define ESTOP_ENABLE 1
+4 -2
View File
@@ -1362,8 +1362,11 @@ status_code_t gc_execute_block(char *block, char *message)
uint_fast8_t idx = N_AXIS;
if (gc_block.modal.units_imperial) do { // Axes indices are consistent, so loop may be used.
idx--;
// if (bit_istrue(axis_words.mask, bit(idx)) && bit_isfalse(settings.steppers.is_rotational.mask, bit(idx)))
#if N_AXIS > 3
if (bit_istrue(axis_words.mask, bit(idx)) && bit_isfalse(settings.steppers.is_rotational.mask, bit(idx)))
#else
if (bit_istrue(axis_words.mask, bit(idx)))
#endif
gc_block.values.xyz[idx] *= MM_PER_INCH;
} while(idx);
@@ -2087,7 +2090,6 @@ status_code_t gc_execute_block(char *block, char *message)
idx = 3;
do { // Axes indices are consistent, so loop may be used to save flash space.
idx--;
// if (ijk_words.mask & bit(idx) && bit_isfalse(settings.steppers.is_rotational.mask, bit(idx)))
if (ijk_words.mask & bit(idx))
gc_block.values.ijk[idx] *= MM_PER_INCH;
} while(idx);
+1 -1
View File
@@ -34,7 +34,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_VERSION_BUILD "20210809"
#define GRBL_VERSION_BUILD "20210819"
// The following symbols are set here if not already set by the compiler or in config.h
// Do NOT change here!
+1 -10
View File
@@ -34,6 +34,7 @@
#include "report.h"
#include "state_machine.h"
#include "nvs_buffer.h"
#include "stream.h"
#ifdef ENABLE_BACKLASH_COMPENSATION
#include "motion_control.h"
#endif
@@ -53,16 +54,6 @@ struct system sys = {0}; //!< System global variable structure.
grbl_t grbl;
grbl_hal_t hal;
// called from stream drivers while tx is blocking, return false to terminate
static bool stream_tx_blocking (void)
{
// TODO: Restructure st_prep_buffer() calls to be executed here during a long print.
grbl.on_execute_realtime(state_get());
return !(sys.rt_exec_state & EXEC_RESET);
}
#ifdef KINEMATICS_API
+7 -3
View File
@@ -566,7 +566,7 @@
#define Z_LIMIT_BIT (1<<Z_LIMIT_PIN)
#endif
#if !defined(X_ENABLE_BIT) && defined(X_ENABLE_BIT)
#if !defined(X_ENABLE_BIT) && defined(X_ENABLE_PIN)
#define X_ENABLE_BIT (1<<X_ENABLE_PIN)
#endif
#if !defined(Y_ENABLE_BIT) && defined(Y_ENABLE_PIN)
@@ -608,6 +608,10 @@
#endif
#endif
#if defined(STEPPERS_ENABLE_PIN) && !defined(STEPPERS_ENABLE_BIT)
#define STEPPERS_ENABLE_BIT (1<<STEPPERS_ENABLE_PIN)
#endif
#ifndef STEPPERS_ENABLE_MASK
#ifdef STEPPERS_ENABLE_BIT
@@ -658,8 +662,8 @@
#endif
#endif
#if N_AXIS >= 6 && !defined(C_LIMIT_BIT)
#ifdef A_LIMIT_PIN
#define C_LIMIT_BIT (1<<A_LIMIT_PIN)
#ifdef C_LIMIT_PIN
#define C_LIMIT_BIT (1<<C_LIMIT_PIN)
#else
#define C_LIMIT_BIT 0
#endif
+86
View File
@@ -0,0 +1,86 @@
/*
pin_bits_masks.h - for adding bit definitions and masks
NOTE: This file is not used by the core, it may be used by drivers
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/>.
*/
#ifdef CONTROL_PORT
#ifndef RESET_PORT
#define RESET_PORT CONTROL_PORT
#endif
#ifndef FEED_HOLD_PORT
#define FEED_HOLD_PORT CONTROL_PORT
#endif
#ifndef CYCLE_START_PORT
#define CYCLE_START_PORT CONTROL_PORT
#endif
#if SAFETY_DOOR_ENABLE && !defined(SAFETY_DOOR_PORT)
#define SAFETY_DOOR_PORT CONTROL_PORT
#endif
#endif
#ifndef RESET_BIT
#define RESET_BIT (1<<RESET_PIN)
#endif
#ifndef FEED_HOLD_BIT
#define FEED_HOLD_BIT (1<<FEED_HOLD_PIN)
#endif
#ifndef CYCLE_START_BIT
#define CYCLE_START_BIT (1<<CYCLE_START_PIN)
#endif
#if SAFETY_DOOR_ENABLE && !defined(SAFETY_DOOR_BIT)
#define SAFETY_DOOR_BIT (1<<SAFETY_DOOR_PIN)
#endif
#ifndef CONTROL_MASK
#if SAFETY_DOOR_ENABLE
#define CONTROL_MASK (RESET_BIT|FEED_HOLD_BIT|CYCLE_START_BIT|SAFETY_DOOR_BIT)
#else
#define CONTROL_MASK (RESET_BIT|FEED_HOLD_BIT|CYCLE_START_BIT)
#endif
#endif
#if defined(SPINDLE_ENABLE_PIN) && !defined(SPINDLE_ENABLE_BIT)
#define SPINDLE_ENABLE_BIT (1<<SPINDLE_ENABLE_PIN)
#endif
#if defined(SPINDLE_DIRECTION_PIN) && !defined(SPINDLE_DIRECTION_BIT)
#define SPINDLE_DIRECTION_BIT (1<<SPINDLE_DIRECTION_PIN)
#endif
#if defined(COOLANT_FLOOD_PIN) && !defined(COOLANT_FLOOD_BIT)
#define COOLANT_FLOOD_BIT (1<<COOLANT_FLOOD_PIN)
#endif
#if defined(COOLANT_MIST_PIN) && !defined(COOLANT_MIST_BIT)
#define COOLANT_MIST_BIT (1<<COOLANT_MIST_PIN)
#endif
#if defined(PROBE_PIN) && !defined(PROBE_BIT)
#define PROBE_BIT (1<<PROBE_PIN)
#endif
#if defined(KEYPAD_STROBE_PIN) && !defined(KEYPAD_STROBE_BIT)
#define KEYPAD_STROBE_BIT (1<<KEYPAD_STROBE_PIN)
#endif
#ifndef AUXINPUT_MASK
#define AUXINPUT_MASK 0
#endif
/*EOF*/
+259 -91
View File
@@ -368,7 +368,7 @@ static void report_group_settings (const setting_group_detail_t *groups, const u
s2++;
}
if(*s1 == '\0') {
report_settings_details(true, Setting_SettingsAll, groups[idx].id);
report_settings_details(SettingsFormat_HumanReadable, Setting_SettingsAll, groups[idx].id);
break;
}
}
@@ -415,7 +415,7 @@ status_code_t report_help (char *args, char *lcargs)
if(grbl.on_report_command_help)
grbl.on_report_command_help();
} else if(!strncmp(args, "SETTINGS", 8))
report_settings_details(true, Setting_SettingsAll, Group_All);
report_settings_details(SettingsFormat_HumanReadable, Setting_SettingsAll, Group_All);
else {
// Strip leading spaces from lowercase version
@@ -953,6 +953,10 @@ void report_build_info (char *line, bool extended)
if(hal.driver_cap.spindle_sync)
strcat(buf, "SS,");
#ifndef NO_SETTINGS_DESCRIPTIONS
strcat(buf, "SED,");
#endif
#ifdef PID_LOG
strcat(buf, "PID,");
#endif
@@ -1377,104 +1381,227 @@ static void report_bitfield (const char *format, bool bitmap)
}
}
static void report_settings_detail (bool human_readable, const setting_detail_t *setting, uint_fast8_t offset)
static void report_settings_detail (settings_format_t format, const setting_detail_t *setting, uint_fast8_t offset)
{
if(human_readable)
hal.stream.write("$");
else
hal.stream.write("[SETTING:");
switch(format)
{
case SettingsFormat_HumanReadable:
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...
hal.stream.write(uitoa(setting->id + offset));
switch(setting_datatype_to_external(setting->datatype)) {
if(human_readable) {
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...
case Format_AxisMask:
hal.stream.write(" as axismask");
break;
switch(setting_datatype_to_external(setting->datatype)) {
case Format_Bool:
hal.stream.write(" as boolean");
break;
case Format_AxisMask:
hal.stream.write(" as axismask");
break;
case Format_Bitfield:
hal.stream.write(" as bitfield:");
report_bitfield(setting->format, true);
break;
case Format_Bool:
hal.stream.write(" as boolean");
break;
case Format_XBitfield:
hal.stream.write(" as bitfield where setting bit 0 enables the rest:");
report_bitfield(setting->format, true);
break;
case Format_Bitfield:
hal.stream.write(" as bitfield:");
report_bitfield(setting->format, true);
break;
case Format_RadioButtons:
hal.stream.write(":");
report_bitfield(setting->format, false);
break;
case Format_XBitfield:
hal.stream.write(" as bitfield where setting bit 0 enables the rest:");
report_bitfield(setting->format, true);
break;
case Format_IPv4:
hal.stream.write(" as IP address");
break;
case Format_RadioButtons:
hal.stream.write(":");
report_bitfield(setting->format, false);
break;
default:
if(setting->unit) {
hal.stream.write(" in ");
hal.stream.write(setting->unit);
}
break;
}
case Format_IPv4:
hal.stream.write(" as IP address");
break;
default:
if(setting->unit) {
hal.stream.write(" in ");
hal.stream.write(setting->unit);
}
break;
}
if(setting->min_value && setting->max_value) {
hal.stream.write(", range: ");
hal.stream.write(setting->min_value);
hal.stream.write(" - ");
hal.stream.write(setting->max_value);
} else if(!setting_is_list(setting)) {
if(setting->min_value) {
hal.stream.write(", min: ");
if(setting->min_value && setting->max_value) {
hal.stream.write(", range: ");
hal.stream.write(setting->min_value);
}
if(setting->max_value) {
hal.stream.write(", max: ");
hal.stream.write(" - ");
hal.stream.write(setting->max_value);
} else if(!setting_is_list(setting)) {
if(setting->min_value) {
hal.stream.write(", min: ");
hal.stream.write(setting->min_value);
}
if(setting->max_value) {
hal.stream.write(", max: ");
hal.stream.write(setting->max_value);
}
}
}
} else {
hal.stream.write(vbar);
hal.stream.write(uitoa(setting->group + (setting->group == Group_Axis0 ? offset : 0)));
hal.stream.write(vbar);
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(vbar);
if(setting->unit)
hal.stream.write(setting->unit);
hal.stream.write(vbar);
hal.stream.write(uitoa(setting_datatype_to_external(setting->datatype)));
hal.stream.write(vbar);
if(setting->format)
hal.stream.write(setting->format);
hal.stream.write(vbar);
if(setting->min_value && !setting_is_list(setting))
hal.stream.write(setting->min_value);
hal.stream.write(vbar);
if(setting->max_value)
hal.stream.write(setting->max_value);
}
break;
if(!human_readable)
hal.stream.write("]");
case SettingsFormat_MachineReadable:
hal.stream.write("[SETTING:");
hal.stream.write(uitoa(setting->id + offset));
hal.stream.write(vbar);
hal.stream.write(uitoa(setting->group + (setting->group == Group_Axis0 ? offset : 0)));
hal.stream.write(vbar);
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(vbar);
if(setting->unit)
hal.stream.write(setting->unit);
hal.stream.write(vbar);
hal.stream.write(uitoa(setting_datatype_to_external(setting->datatype)));
hal.stream.write(vbar);
if(setting->format)
hal.stream.write(setting->format);
hal.stream.write(vbar);
if(setting->min_value && !setting_is_list(setting))
hal.stream.write(setting->min_value);
hal.stream.write(vbar);
if(setting->max_value)
hal.stream.write(setting->max_value);
hal.stream.write("]");
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
break;
case SettingsFormat_grblHAL:
hal.stream.write(uitoa(setting->id + offset));
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...
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:
hal.stream.write("integer");
break;
case Format_Decimal:
hal.stream.write("float");
break;
case Format_Bool:
hal.stream.write("bool");
break;
case Format_AxisMask:
case Format_Bitfield:
hal.stream.write("bitfield");
break;
case Format_XBitfield:
hal.stream.write("xbitfield");
break;
case Format_RadioButtons:
hal.stream.write("radiobuttons");
break;
case Format_IPv4:
hal.stream.write("ipv4");
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
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;
}
hal.stream.write(ASCII_EOL);
}
typedef struct {
bool human_readable;
settings_format_t format;
setting_group_t group;
uint_fast16_t offset;
} report_args_t;
@@ -1482,12 +1609,12 @@ typedef struct {
static bool print_sorted (const setting_detail_t *setting, uint_fast16_t offset, void *args)
{
if(!(((report_args_t *)args)->group == setting->group && ((report_args_t *)args)->offset != offset))
report_settings_detail (((report_args_t *)args)->human_readable, setting, offset);
report_settings_detail (((report_args_t *)args)->format, setting, offset);
return true;
}
static status_code_t sort_settings_details (bool human_readable, setting_group_t group)
static status_code_t sort_settings_details (settings_format_t format, setting_group_t group)
{
bool reported = group == Group_All;
@@ -1498,7 +1625,7 @@ static status_code_t sort_settings_details (bool human_readable, setting_group_t
args.group = settings_normalize_group(group);
args.offset = group - args.group;
args.human_readable = human_readable;
args.format = format;
while(details->on_get_settings) {
details = details->on_get_settings();
@@ -1537,6 +1664,11 @@ static status_code_t sort_settings_details (bool human_readable, setting_group_t
qsort(all_settings, n_settings, sizeof(setting_detail_t *), cmp_settings);
if(format == SettingsFormat_Grbl)
hal.stream.write("\"$-Code\",\" Setting\",\" Units\",\" Setting Description\"" ASCII_EOL);
else if(format == SettingsFormat_grblHAL)
hal.stream.write("$-Code\tSetting\tUnits\tDatatype\tData format\tSetting Description\tMin\tMax" ASCII_EOL);
for(idx = 0; idx < n_settings; idx++) {
if(settings_iterator(all_settings[idx], print_sorted, &args))
reported = true;
@@ -1552,16 +1684,16 @@ static bool print_unsorted (const setting_detail_t *setting, uint_fast16_t offse
{
if(!(((report_args_t *)args)->group == setting->group && ((report_args_t *)args)->offset != offset) &&
(setting->is_available == NULL ||setting->is_available(setting)))
report_settings_detail(((report_args_t *)args)->human_readable, setting, offset);
report_settings_detail(((report_args_t *)args)->format, setting, offset);
return true;
}
static status_code_t print_settings_details (bool human_readable, setting_group_t group, uint_fast16_t axis_rpt)
static status_code_t print_settings_details (settings_format_t format, setting_group_t group, uint_fast16_t axis_rpt)
{
status_code_t status;
if((status = sort_settings_details(human_readable, group)) != Status_Unhandled)
if((status = sort_settings_details(format, group)) != Status_Unhandled)
return status;
bool reported = group == Group_All;
@@ -1572,7 +1704,7 @@ static status_code_t print_settings_details (bool human_readable, setting_group_
args.group = settings_normalize_group(group);
args.offset = group - args.group;
args.human_readable = human_readable;
args.format = format;
do {
for(idx = 0; idx < settings->n_settings; idx++) {
@@ -1590,7 +1722,7 @@ static status_code_t print_settings_details (bool human_readable, setting_group_
return reported ? Status_OK : Status_SettingDisabled;
}
status_code_t report_settings_details (bool human_readable, setting_id_t id, setting_group_t group)
status_code_t report_settings_details (settings_format_t format, setting_id_t id, setting_group_t group)
{
uint_fast16_t axis_rpt = 0;
@@ -1600,16 +1732,52 @@ status_code_t report_settings_details (bool human_readable, setting_id_t id, set
const setting_detail_t *setting = setting_get_details(id, NULL);
if(setting)
report_settings_detail(human_readable, setting, id - setting->id);
report_settings_detail(format, setting, id - setting->id);
else
status = Status_SettingDisabled;
return status;
}
return print_settings_details(human_readable, group, axis_rpt);
return print_settings_details(format, group, axis_rpt);
}
#ifndef NO_SETTINGS_DESCRIPTIONS
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);
if(format == SettingsFormat_MachineReadable) {
hal.stream.write("[SETTINGDESCR:");
hal.stream.write(uitoa(id));
hal.stream.write(vbar);
}
// hal.stream.write(description == NULL ? (is_setting_available(setting_get_details(id, NULL)) ? "" : "N/A") : description); // TODO?
hal.stream.write(description == NULL ? (setting_get_details(id, NULL) ? "" : "N/A") : description);
if(format == SettingsFormat_MachineReadable)
hal.stream.write("]" ASCII_EOL);
return Status_OK;
}
#endif
status_code_t report_alarm_details (void)
{
uint_fast16_t idx, n_alarms = sizeof(alarm_detail) / sizeof(alarm_detail_t);
+11 -1
View File
@@ -32,6 +32,13 @@ typedef enum {
Message_Warning
} message_type_t;
typedef enum {
SettingsFormat_MachineReadable = 0,
SettingsFormat_HumanReadable,
SettingsFormat_Grbl,
SettingsFormat_grblHAL
} settings_format_t;
// Initialize reporting subsystem
void report_init (void);
void report_init_fns (void);
@@ -89,7 +96,10 @@ 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_setting_group_details (bool by_id, char *prefix);
status_code_t report_settings_details (bool human_readable, setting_id_t setting, setting_group_t group);
status_code_t report_settings_details (settings_format_t format, setting_id_t setting, setting_group_t group);
#ifndef NO_SETTINGS_DESCRIPTIONS
status_code_t report_setting_description (settings_format_t format, setting_id_t id);
#endif
status_code_t report_last_signals_event (sys_state_t state, char *args);
status_code_t report_current_limit_state (sys_state_t state, char *args);
+275 -118
View File
@@ -100,7 +100,9 @@ PROGMEM const settings_t defaults = {
.steppers.dir_invert.mask = DEFAULT_DIRECTION_INVERT_MASK,
.steppers.enable_invert.mask = INVERT_ST_ENABLE_MASK,
.steppers.deenergize.mask = ST_DEENERGIZE_MASK,
// .steppers.is_rotational.mask = 0,
#if N_AXIS > 3
.steppers.is_rotational.mask = (ST_ROTATIONAL_MASK & AXES_BITMASK) >> 3,
#endif
#if DEFAULT_HOMING_ENABLE
.homing.flags.enabled = DEFAULT_HOMING_ENABLE,
.homing.flags.init_lock = DEFAULT_HOMING_INIT_LOCK,
@@ -281,39 +283,39 @@ PROGMEM const settings_t defaults = {
};
PROGMEM static const setting_group_detail_t setting_group_detail [] = {
{ Group_Root, Group_Root, "Root"},
{ Group_Root, Group_General, "General"},
{ Group_Root, Group_ControlSignals, "Control signals"},
{ Group_Root, Group_Limits, "Limits"},
{ Group_Limits, Group_Limits_DualAxis, "Dual axis"},
{ Group_Root, Group_Coolant, "Coolant"},
{ Group_Root, Group_Spindle, "Spindle"},
{ Group_Spindle, Group_Spindle_Sync, "Spindle sync"},
{ Group_Root, Group_Toolchange, "Tool change"},
{ Group_Root, Group_Homing, "Homing"},
{ Group_Root, Group_Probing, "Probing"},
{ Group_Root, Group_SafetyDoor, "Safety door"},
{ Group_Root, Group_Jogging, "Jogging"},
{ Group_Root, Group_Stepper, "Stepper"},
{ Group_Root, Group_MotorDriver, "Stepper driver"},
{ Group_Root, Group_Axis, "Axis"},
{ Group_Axis, Group_XAxis, "X-axis"},
{ Group_Axis, Group_YAxis, "Y-axis"},
{ Group_Axis, Group_ZAxis, "Z-axis"},
{ Group_Root, Group_Root, "Root"},
{ Group_Root, Group_General, "General"},
{ Group_Root, Group_ControlSignals, "Control signals"},
{ Group_Root, Group_Limits, "Limits"},
{ Group_Limits, Group_Limits_DualAxis, "Dual axis"},
{ Group_Root, Group_Coolant, "Coolant"},
{ Group_Root, Group_Spindle, "Spindle"},
{ Group_Spindle, Group_Spindle_Sync, "Spindle sync"},
{ Group_Root, Group_Toolchange, "Tool change"},
{ Group_Root, Group_Homing, "Homing"},
{ Group_Root, Group_Probing, "Probing"},
{ Group_Root, Group_SafetyDoor, "Safety door"},
{ Group_Root, Group_Jogging, "Jogging"},
{ Group_Root, Group_Stepper, "Stepper"},
{ Group_Root, Group_MotorDriver, "Stepper driver"},
{ Group_Root, Group_Axis, "Axis"},
{ Group_Axis, Group_XAxis, "X-axis"},
{ Group_Axis, Group_YAxis, "Y-axis"},
{ Group_Axis, Group_ZAxis, "Z-axis"},
#ifdef A_AXIS
{ Group_Axis, Group_AAxis, "A-axis"},
{ Group_Axis, Group_AAxis, "A-axis"},
#endif
#ifdef B_AXIS
{ Group_Axis, Group_BAxis, "B-axis"},
{ Group_Axis, Group_BAxis, "B-axis"},
#endif
#ifdef C_AXIS
{ Group_Axis, Group_CAxis, "C-axis"},
{ Group_Axis, Group_CAxis, "C-axis"},
#endif
#ifdef U_AXIS
{ Group_Axis, Group_UAxis, "U-axis"},
{ Group_Axis, Group_UAxis, "U-axis"},
#endif
#ifdef V_AXIS
{ Group_Axis, Group_VAxis, "V-axis"}
{ Group_Axis, Group_VAxis, "V-axis"}
#endif
};
@@ -346,6 +348,9 @@ static status_code_t set_door_options (setting_id_t id, uint_fast16_t int_value)
static status_code_t set_linear_piece (setting_id_t id, char *svalue);
static char *get_linear_piece (setting_id_t id);
#endif
#if N_AXIS > 3
static status_code_t set_rotational_axes (setting_id_t id, uint_fast16_t int_value);
#endif
#if COMPATIBILITY_LEVEL > 1
static status_code_t set_limits_invert_mask (setting_id_t id, uint_fast16_t int_value);
#endif
@@ -359,131 +364,268 @@ static char spindle_signals[] = "Spindle enable,Spindle direction,PWM";
static char coolant_signals[] = "Flood,Mist";
PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_PulseMicroseconds, Group_Stepper, "Step pulse time", "microseconds", Format_Decimal, "#0.0", "2.0", NULL, Setting_IsLegacy, &settings.steppers.pulse_microseconds, NULL, NULL },
{ Setting_StepperIdleLockTime, Group_Stepper, "Step idle delay", "milliseconds", Format_Int16, "####0", NULL, "65535", Setting_IsLegacy, &settings.steppers.idle_lock_time, NULL, NULL },
{ Setting_StepInvertMask, Group_Stepper, "Step pulse invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.steppers.step_invert.mask, NULL, NULL },
{ Setting_DirInvertMask, Group_Stepper, "Step direction invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.steppers.dir_invert.mask, NULL, NULL },
{ Setting_InvertStepperEnable, Group_Stepper, "Invert step enable pin(s)", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.steppers.enable_invert.mask, NULL, NULL },
{ Setting_PulseMicroseconds, Group_Stepper, "Step pulse time", "microseconds", Format_Decimal, "#0.0", "2.0", NULL, Setting_IsLegacy, &settings.steppers.pulse_microseconds, NULL, NULL },
{ Setting_StepperIdleLockTime, Group_Stepper, "Step idle delay", "milliseconds", Format_Int16, "####0", NULL, "65535", Setting_IsLegacy, &settings.steppers.idle_lock_time, NULL, NULL },
{ Setting_StepInvertMask, Group_Stepper, "Step pulse invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.steppers.step_invert.mask, NULL, NULL },
{ Setting_DirInvertMask, Group_Stepper, "Step direction invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.steppers.dir_invert.mask, NULL, NULL },
{ Setting_InvertStepperEnable, Group_Stepper, "Invert step enable pin(s)", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.steppers.enable_invert.mask, NULL, NULL },
#if COMPATIBILITY_LEVEL <= 1
{ Setting_LimitPinsInvertMask, Group_Limits, "Invert limit pins", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.limits.invert.mask, NULL, NULL },
{ Setting_LimitPinsInvertMask, Group_Limits, "Invert limit pins", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.limits.invert.mask, NULL, NULL },
#else
{ Setting_LimitPinsInvertMask, Group_Limits, "Invert limit pins", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_limits_invert_mask, get_int, NULL },
{ Setting_LimitPinsInvertMask, Group_Limits, "Invert limit pins", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_limits_invert_mask, get_int, NULL },
#endif
{ Setting_InvertProbePin, Group_Probing, "Invert probe pin", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_probe_invert, get_int, NULL },
{ Setting_SpindlePWMBehaviour, Group_Spindle, "Disable spindle with zero speed", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtended, &settings.spindle.flags.mask, NULL, is_setting_available },
// { Setting_SpindlePWMBehaviour, Group_Spindle, "Spindle enable vs. speed behaviour", NULL, Format_RadioButtons, "No action,Disable spindle with zero speed,Enable spindle with all speeds", NULL, NULL, Setting_IsExtended, &settings.spindle.flags.mask, NULL, NULL },
{ Setting_InvertProbePin, Group_Probing, "Invert probe pin", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_probe_invert, get_int, NULL },
{ Setting_SpindlePWMBehaviour, Group_Spindle, "Disable spindle with zero speed", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtended, &settings.spindle.flags.mask, NULL, is_setting_available },
// { Setting_SpindlePWMBehaviour, Group_Spindle, "Spindle enable vs. speed behaviour", NULL, Format_RadioButtons, "No action,Disable spindle with zero speed,Enable spindle with all speeds", NULL, NULL, Setting_IsExtended, &settings.spindle.flags.mask, NULL, NULL },
#if COMPATIBILITY_LEVEL <= 1
{ Setting_StatusReportMask, Group_General, "Status report options", NULL, Format_Bitfield, "Position in machine coordinate,Buffer state,Line numbers,Feed & speed,Pin state,Work coordinate offset,Overrides,Probe coordinates,Buffer sync on WCO change,Parser state,Alarm substatus,Run substatus", NULL, NULL, Setting_IsExtendedFn, set_report_mask, get_int, NULL },
{ Setting_StatusReportMask, Group_General, "Status report options", NULL, Format_Bitfield, "Position in machine coordinate,Buffer state,Line numbers,Feed & speed,Pin state,Work coordinate offset,Overrides,Probe coordinates,Buffer sync on WCO change,Parser state,Alarm substatus,Run substatus", NULL, NULL, Setting_IsExtendedFn, set_report_mask, get_int, NULL },
#else
{ Setting_StatusReportMask, Group_General, "Status report options", NULL, Format_Bitfield, "Position in machine coordinate,Buffer state", NULL, NULL, Setting_IsLegacyFn, set_report_mask, get_int, NULL },
{ Setting_StatusReportMask, Group_General, "Status report options", NULL, Format_Bitfield, "Position in machine coordinate,Buffer state", NULL, NULL, Setting_IsLegacyFn, set_report_mask, get_int, NULL },
#endif
{ Setting_JunctionDeviation, Group_General, "Junction deviation", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.junction_deviation, NULL, NULL },
{ Setting_ArcTolerance, Group_General, "Arc tolerance", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.arc_tolerance, NULL, NULL },
{ Setting_ReportInches, Group_General, "Report in inches", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_report_inches, get_int, NULL },
{ Setting_ControlInvertMask, Group_ControlSignals, "Invert control pins", NULL, Format_Bitfield, control_signals, NULL, NULL, Setting_IsExpandedFn, set_control_invert, get_int, NULL },
{ Setting_CoolantInvertMask, Group_Coolant, "Invert coolant pins", NULL, Format_Bitfield, coolant_signals, NULL, NULL, Setting_IsExtended, &settings.coolant_invert.mask, NULL, NULL },
{ Setting_SpindleInvertMask, Group_Spindle, "Invert spindle signals", NULL, Format_Bitfield, spindle_signals, NULL, NULL, Setting_IsExtendedFn, set_spindle_invert, get_int, NULL },
{ Setting_ControlPullUpDisableMask, Group_ControlSignals, "Pullup disable control pins", NULL, Format_Bitfield, control_signals, NULL, NULL, Setting_IsExtendedFn, set_control_disable_pullup, get_int, NULL },
{ Setting_LimitPullUpDisableMask, Group_Limits, "Pullup disable limit pins", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.limits.disable_pullup.mask, NULL, NULL },
{ Setting_ProbePullUpDisable, Group_Probing, "Pullup disable probe pin", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_probe_disable_pullup, get_int, NULL },
{ Setting_SoftLimitsEnable, Group_Limits, "Soft limits enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_soft_limits_enable, get_int, NULL },
{ Setting_JunctionDeviation, Group_General, "Junction deviation", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.junction_deviation, NULL, NULL },
{ Setting_ArcTolerance, Group_General, "Arc tolerance", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.arc_tolerance, NULL, NULL },
{ Setting_ReportInches, Group_General, "Report in inches", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_report_inches, get_int, NULL },
{ Setting_ControlInvertMask, Group_ControlSignals, "Invert control pins", NULL, Format_Bitfield, control_signals, NULL, NULL, Setting_IsExpandedFn, set_control_invert, get_int, NULL },
{ Setting_CoolantInvertMask, Group_Coolant, "Invert coolant pins", NULL, Format_Bitfield, coolant_signals, NULL, NULL, Setting_IsExtended, &settings.coolant_invert.mask, NULL, NULL },
{ Setting_SpindleInvertMask, Group_Spindle, "Invert spindle signals", NULL, Format_Bitfield, spindle_signals, NULL, NULL, Setting_IsExtendedFn, set_spindle_invert, get_int, NULL },
{ Setting_ControlPullUpDisableMask, Group_ControlSignals, "Pullup disable control pins", NULL, Format_Bitfield, control_signals, NULL, NULL, Setting_IsExtendedFn, set_control_disable_pullup, get_int, NULL },
{ Setting_LimitPullUpDisableMask, Group_Limits, "Pullup disable limit pins", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.limits.disable_pullup.mask, NULL, NULL },
{ Setting_ProbePullUpDisable, Group_Probing, "Pullup disable probe pin", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_probe_disable_pullup, get_int, NULL },
{ Setting_SoftLimitsEnable, Group_Limits, "Soft limits enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_soft_limits_enable, get_int, NULL },
#if COMPATIBILITY_LEVEL <= 1
{ Setting_HardLimitsEnable, Group_Limits, "Hard limits enable", NULL, Format_XBitfield, "Enable,Strict mode", NULL, NULL, Setting_IsExpandedFn, set_hard_limits_enable, get_int, NULL },
{ Setting_HardLimitsEnable, Group_Limits, "Hard limits enable", NULL, Format_XBitfield, "Enable,Strict mode", NULL, NULL, Setting_IsExpandedFn, set_hard_limits_enable, get_int, NULL },
#else
{ Setting_HardLimitsEnable, Group_Limits, "Hard limits enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_hard_limits_enable, get_int, NULL },
{ Setting_HardLimitsEnable, Group_Limits, "Hard limits enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_hard_limits_enable, get_int, NULL },
#endif
#if COMPATIBILITY_LEVEL <= 1
{ Setting_HomingEnable, Group_Homing, "Homing cycle", NULL, Format_XBitfield, "Enable,Enable single axis commands,Homing on startup required,Set machine origin to 0,Two switches shares one input pin,Allow manual,Override locks,Keep homed status on reset", NULL, NULL, Setting_IsExpandedFn, set_homing_enable, get_int, NULL },
{ Setting_HomingEnable, Group_Homing, "Homing cycle", NULL, Format_XBitfield, "Enable,Enable single axis commands,Homing on startup required,Set machine origin to 0,Two switches shares one input pin,Allow manual,Override locks,Keep homed status on reset", NULL, NULL, Setting_IsExpandedFn, set_homing_enable, get_int, NULL },
#else
{ Setting_HomingEnable, Group_Homing, "Homing cycle enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_homing_enable, get_int, NULL },
{ Setting_HomingEnable, Group_Homing, "Homing cycle enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_homing_enable, get_int, NULL },
#endif
{ Setting_HomingDirMask, Group_Homing, "Homing direction invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.homing.dir_mask.value, NULL, NULL },
{ Setting_HomingFeedRate, Group_Homing, "Homing locate feed rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsLegacy, &settings.homing.feed_rate, NULL, NULL },
{ Setting_HomingSeekRate, Group_Homing, "Homing search seek rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsLegacy, &settings.homing.seek_rate, NULL, NULL },
{ Setting_HomingDebounceDelay, Group_Homing, "Homing switch debounce delay", "milliseconds", Format_Int16, "##0", NULL, NULL, Setting_IsLegacy, &settings.homing.debounce_delay, NULL, NULL },
{ Setting_HomingPulloff, Group_Homing, "Homing switch pull-off distance", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.homing.pulloff, NULL, NULL },
{ Setting_G73Retract, Group_General, "G73 Retract distance", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsExtended, &settings.g73_retract, NULL, NULL },
{ Setting_PulseDelayMicroseconds, Group_Stepper, "Pulse delay", "microseconds", Format_Decimal, "#0.0", NULL, "10", Setting_IsExtended, &settings.steppers.pulse_delay_microseconds, NULL, NULL },
{ Setting_RpmMax, Group_Spindle, "Maximum spindle speed", "RPM", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.spindle.rpm_max, NULL, is_setting_available },
{ Setting_RpmMin, Group_Spindle, "Minimum spindle speed", "RPM", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.spindle.rpm_min, NULL, is_setting_available },
{ Setting_Mode, Group_General, "Mode of operation", NULL, Format_RadioButtons, "Normal,Laser mode,Lathe mode", NULL, NULL, Setting_IsLegacyFn, set_mode, get_int, NULL },
{ Setting_PWMFreq, Group_Spindle, "Spindle PWM frequency", "Hz", Format_Decimal, "#####0", NULL, NULL, Setting_IsExtended, &settings.spindle.pwm_freq, NULL, is_setting_available },
{ Setting_PWMOffValue, Group_Spindle, "Spindle PWM off value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &settings.spindle.pwm_off_value, NULL, is_setting_available },
{ Setting_PWMMinValue, Group_Spindle, "Spindle PWM min value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &settings.spindle.pwm_min_value, NULL, is_setting_available },
{ Setting_PWMMaxValue, Group_Spindle, "Spindle PWM max value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &settings.spindle.pwm_max_value, NULL, is_setting_available },
{ Setting_StepperDeenergizeMask, Group_Stepper, "Steppers deenergize", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.steppers.deenergize.mask, NULL, NULL },
{ Setting_SpindlePPR, Group_Spindle, "Spindle pulses per revolution (PPR)", NULL, Format_Int16, "###0", NULL, NULL, Setting_IsExtended, &settings.spindle.ppr, NULL, is_setting_available },
{ Setting_EnableLegacyRTCommands, Group_General, "Enable legacy RT commands", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_enable_legacy_rt_commands, get_int, NULL },
{ Setting_JogSoftLimited, Group_Jogging, "Limit jog commands", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_jog_soft_limited, get_int, NULL },
{ Setting_HomingDirMask, Group_Homing, "Homing direction invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.homing.dir_mask.value, NULL, NULL },
{ Setting_HomingFeedRate, Group_Homing, "Homing locate feed rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsLegacy, &settings.homing.feed_rate, NULL, NULL },
{ Setting_HomingSeekRate, Group_Homing, "Homing search seek rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsLegacy, &settings.homing.seek_rate, NULL, NULL },
{ Setting_HomingDebounceDelay, Group_Homing, "Homing switch debounce delay", "milliseconds", Format_Int16, "##0", NULL, NULL, Setting_IsLegacy, &settings.homing.debounce_delay, NULL, NULL },
{ Setting_HomingPulloff, Group_Homing, "Homing switch pull-off distance", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.homing.pulloff, NULL, NULL },
{ Setting_G73Retract, Group_General, "G73 Retract distance", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsExtended, &settings.g73_retract, NULL, NULL },
{ Setting_PulseDelayMicroseconds, Group_Stepper, "Pulse delay", "microseconds", Format_Decimal, "#0.0", NULL, "10", Setting_IsExtended, &settings.steppers.pulse_delay_microseconds, NULL, NULL },
{ Setting_RpmMax, Group_Spindle, "Maximum spindle speed", "RPM", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.spindle.rpm_max, NULL, is_setting_available },
{ Setting_RpmMin, Group_Spindle, "Minimum spindle speed", "RPM", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.spindle.rpm_min, NULL, is_setting_available },
{ Setting_Mode, Group_General, "Mode of operation", NULL, Format_RadioButtons, "Normal,Laser mode,Lathe mode", NULL, NULL, Setting_IsLegacyFn, set_mode, get_int, NULL },
{ Setting_PWMFreq, Group_Spindle, "Spindle PWM frequency", "Hz", Format_Decimal, "#####0", NULL, NULL, Setting_IsExtended, &settings.spindle.pwm_freq, NULL, is_setting_available },
{ Setting_PWMOffValue, Group_Spindle, "Spindle PWM off value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &settings.spindle.pwm_off_value, NULL, is_setting_available },
{ Setting_PWMMinValue, Group_Spindle, "Spindle PWM min value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &settings.spindle.pwm_min_value, NULL, is_setting_available },
{ Setting_PWMMaxValue, Group_Spindle, "Spindle PWM max value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &settings.spindle.pwm_max_value, NULL, is_setting_available },
{ Setting_StepperDeenergizeMask, Group_Stepper, "Steppers deenergize", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.steppers.deenergize.mask, NULL, NULL },
{ Setting_SpindlePPR, Group_Spindle, "Spindle pulses per revolution (PPR)", NULL, Format_Int16, "###0", NULL, NULL, Setting_IsExtended, &settings.spindle.ppr, NULL, is_setting_available },
{ Setting_EnableLegacyRTCommands, Group_General, "Enable legacy RT commands", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_enable_legacy_rt_commands, get_int, NULL },
{ Setting_JogSoftLimited, Group_Jogging, "Limit jog commands", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_jog_soft_limited, get_int, NULL },
#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
{ Setting_ParkingEnable, Group_SafetyDoor, "Parking cycle", NULL, Format_XBitfield, "Enable,Enable parking override control,Deactivate upon init", NULL, NULL, Setting_IsExtendedFn, set_parking_enable, get_int, NULL },
{ Setting_ParkingAxis, Group_SafetyDoor, "Parking axis", NULL, Format_RadioButtons, "X,Y,Z", NULL, NULL, Setting_IsExtended, &settings.parking.axis, NULL, NULL },
{ Setting_ParkingEnable, Group_SafetyDoor, "Parking cycle", NULL, Format_XBitfield, "Enable,Enable parking override control,Deactivate upon init", NULL, NULL, Setting_IsExtendedFn, set_parking_enable, get_int, NULL },
{ Setting_ParkingAxis, Group_SafetyDoor, "Parking axis", NULL, Format_RadioButtons, "X,Y,Z", NULL, NULL, Setting_IsExtended, &settings.parking.axis, NULL, NULL },
#endif
{ Setting_HomingLocateCycles, Group_Homing, "Homing passes", NULL, Format_Int8, "##0", "1", "128", Setting_IsExtended, &settings.homing.locate_cycles, NULL, NULL },
{ Setting_HomingCycle_1, Group_Homing, "Axes homing, first pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_2, Group_Homing, "Axes homing, second pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_3, Group_Homing, "Axes homing, third pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingLocateCycles, Group_Homing, "Homing passes", NULL, Format_Int8, "##0", "1", "128", Setting_IsExtended, &settings.homing.locate_cycles, NULL, NULL },
{ Setting_HomingCycle_1, Group_Homing, "Axes homing, first pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_2, Group_Homing, "Axes homing, second pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_3, Group_Homing, "Axes homing, third pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
#ifdef A_AXIS
{ Setting_HomingCycle_4, Group_Homing, "Axes homing, fourth pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_4, Group_Homing, "Axes homing, fourth pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
#endif
#ifdef B_AXIS
{ Setting_HomingCycle_5, Group_Homing, "Axes homing, fifth pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_5, Group_Homing, "Axes homing, fifth pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
#endif
#ifdef C_AXIS
{ Setting_HomingCycle_6, Group_Homing, "Axes homing, sixth pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_6, Group_Homing, "Axes homing, sixth pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
#endif
#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
{ Setting_ParkingPulloutIncrement, Group_SafetyDoor, "Parking pull-out distance", "mm", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.pullout_increment, NULL, NULL },
{ Setting_ParkingPulloutRate, Group_SafetyDoor, "Parking pull-out rate", "mm/min", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.pullout_rate, NULL, NULL },
{ Setting_ParkingTarget, Group_SafetyDoor, "Parking target", "mm", Format_Decimal, "-###0.0", "-100000", NULL, Setting_IsExtended, &settings.parking.target, NULL, NULL },
{ Setting_ParkingFastRate, Group_SafetyDoor, "Parking fast rate", "mm/min", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.rate, NULL, NULL },
{ Setting_RestoreOverrides, Group_General, "Restore overrides", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_restore_overrides, get_int, NULL },
{ Setting_DoorOptions, Group_SafetyDoor, "Safety door options", NULL, Format_Bitfield, "Ignore when idle,Keep coolant state on open", NULL, NULL, Setting_IsExtendedFn, set_door_options, get_int, NULL },
{ Setting_ParkingPulloutIncrement, Group_SafetyDoor, "Parking pull-out distance", "mm", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.pullout_increment, NULL, NULL },
{ Setting_ParkingPulloutRate, Group_SafetyDoor, "Parking pull-out rate", "mm/min", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.pullout_rate, NULL, NULL },
{ Setting_ParkingTarget, Group_SafetyDoor, "Parking target", "mm", Format_Decimal, "-###0.0", "-100000", NULL, Setting_IsExtended, &settings.parking.target, NULL, NULL },
{ Setting_ParkingFastRate, Group_SafetyDoor, "Parking fast rate", "mm/min", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.rate, NULL, NULL },
{ Setting_RestoreOverrides, Group_General, "Restore overrides", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_restore_overrides, get_int, NULL },
{ Setting_DoorOptions, Group_SafetyDoor, "Safety door options", NULL, Format_Bitfield, "Ignore when idle,Keep coolant state on open", NULL, NULL, Setting_IsExtendedFn, set_door_options, get_int, NULL },
#endif
{ Setting_SleepEnable, Group_General, "Sleep enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_sleep_enable, get_int, NULL },
{ Setting_HoldActions, Group_General, "Feed hold actions", NULL, Format_Bitfield, "Disable laser during hold,Restore spindle and coolant state on resume", NULL, NULL, Setting_IsExtendedFn, set_hold_actions, get_int, NULL },
{ Setting_ForceInitAlarm, Group_General, "Force init alarm", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_force_initialization_alarm, get_int, NULL },
{ Setting_ProbingFeedOverride, Group_Probing, "Probing feed override", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_probe_allow_feed_override, get_int, NULL },
{ Setting_SleepEnable, Group_General, "Sleep enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_sleep_enable, get_int, NULL },
{ Setting_HoldActions, Group_General, "Feed hold actions", NULL, Format_Bitfield, "Disable laser during hold,Restore spindle and coolant state on resume", NULL, NULL, Setting_IsExtendedFn, set_hold_actions, get_int, NULL },
{ Setting_ForceInitAlarm, Group_General, "Force init alarm", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_force_initialization_alarm, get_int, NULL },
{ Setting_ProbingFeedOverride, Group_Probing, "Probing feed override", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_probe_allow_feed_override, get_int, NULL },
#ifdef ENABLE_SPINDLE_LINEARIZATION
{ Setting_LinearSpindlePiece1, Group_Spindle, "Spindle linearisation, first point", NULL, Format_String, "x30", NULL, "30", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
{ Setting_LinearSpindlePiece2, Group_Spindle, "Spindle linearisation, second point", NULL, Format_String, "x30", NULL, "30", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
{ Setting_LinearSpindlePiece3, Group_Spindle, "Spindle linearisation, third point", NULL, Format_String, "x30", NULL, "30", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
{ Setting_LinearSpindlePiece4, Group_Spindle, "Spindle linearisation, fourth point", NULL, Format_String, "x30", NULL, "30", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
{ Setting_LinearSpindlePiece1, Group_Spindle, "Spindle linearisation, first point", NULL, Format_String, "x30", NULL, "30", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
{ Setting_LinearSpindlePiece2, Group_Spindle, "Spindle linearisation, second point", NULL, Format_String, "x30", NULL, "30", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
{ Setting_LinearSpindlePiece3, Group_Spindle, "Spindle linearisation, third point", NULL, Format_String, "x30", NULL, "30", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
{ Setting_LinearSpindlePiece4, Group_Spindle, "Spindle linearisation, fourth point", NULL, Format_String, "x30", NULL, "30", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
#endif
{ Setting_SpindlePGain, Group_Spindle_ClosedLoop, "Spindle P-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.spindle.pid.p_gain, NULL, NULL },
{ Setting_SpindleIGain, Group_Spindle_ClosedLoop, "Spindle I-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.spindle.pid.i_gain, NULL, NULL },
{ Setting_SpindleDGain, Group_Spindle_ClosedLoop, "Spindle D-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.spindle.pid.d_gain, NULL, NULL },
{ Setting_SpindleMaxError, Group_Spindle_ClosedLoop, "Spindle PID max error", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.spindle.pid.max_error, NULL, NULL },
{ Setting_SpindleIMaxError, Group_Spindle_ClosedLoop, "Spindle PID max I error", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.spindle.pid.i_max_error, NULL, NULL },
{ Setting_PositionPGain, Group_Spindle_Sync, "Spindle sync P-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.position.pid.p_gain, NULL, NULL },
{ Setting_PositionIGain, Group_Spindle_Sync, "Spindle sync I-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.position.pid.i_gain, NULL, NULL },
{ Setting_PositionDGain, Group_Spindle_Sync, "Spindle sync D-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.position.pid.d_gain, NULL, NULL },
{ Setting_PositionIMaxError, Group_Spindle_Sync, "Spindle sync PID max I error", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.position.pid.i_max_error, NULL, NULL },
{ Setting_AxisStepsPerMM, Group_Axis0, "?-axis travel resolution", "step/mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
{ Setting_AxisMaxRate, Group_Axis0, "?-axis maximum rate", "mm/min", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
{ Setting_AxisAcceleration, Group_Axis0, "?-axis acceleration", "mm/sec^2", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
{ Setting_AxisMaxTravel, Group_Axis0, "?-axis maximum travel", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
{ Setting_SpindlePGain, Group_Spindle_ClosedLoop, "Spindle P-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.spindle.pid.p_gain, NULL, NULL },
{ Setting_SpindleIGain, Group_Spindle_ClosedLoop, "Spindle I-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.spindle.pid.i_gain, NULL, NULL },
{ Setting_SpindleDGain, Group_Spindle_ClosedLoop, "Spindle D-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.spindle.pid.d_gain, NULL, NULL },
{ Setting_SpindleMaxError, Group_Spindle_ClosedLoop, "Spindle PID max error", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.spindle.pid.max_error, NULL, NULL },
{ Setting_SpindleIMaxError, Group_Spindle_ClosedLoop, "Spindle PID max I error", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.spindle.pid.i_max_error, NULL, NULL },
{ Setting_PositionPGain, Group_Spindle_Sync, "Spindle sync P-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.position.pid.p_gain, NULL, NULL },
{ Setting_PositionIGain, Group_Spindle_Sync, "Spindle sync I-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.position.pid.i_gain, NULL, NULL },
{ Setting_PositionDGain, Group_Spindle_Sync, "Spindle sync D-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.position.pid.d_gain, NULL, NULL },
{ Setting_PositionIMaxError, Group_Spindle_Sync, "Spindle sync PID max I error", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.position.pid.i_max_error, NULL, NULL },
{ Setting_AxisStepsPerMM, Group_Axis0, "?-axis travel resolution", "step/mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
{ Setting_AxisMaxRate, Group_Axis0, "?-axis maximum rate", "mm/min", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
{ Setting_AxisAcceleration, Group_Axis0, "?-axis acceleration", "mm/sec^2", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
{ Setting_AxisMaxTravel, Group_Axis0, "?-axis maximum travel", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
#ifdef ENABLE_BACKLASH_COMPENSATION
{ Setting_AxisBacklash, Group_Axis0, "?-axis backlash compensation", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsExtendedFn, set_axis_setting, get_float, NULL, NULL },
{ Setting_AxisBacklash, Group_Axis0, "?-axis backlash compensation", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsExtendedFn, set_axis_setting, get_float, NULL, NULL },
#endif
{ Setting_AxisAutoSquareOffset, Group_Axis0, "?-axis dual axis offset", "mm", Format_Decimal, "-0.000", "-2", "2", Setting_IsExtendedFn, set_axis_setting, get_float, is_setting_available },
{ Setting_SpindleAtSpeedTolerance, Group_Spindle, "Spindle at speed tolerance", "percent", Format_Decimal, "##0.0", NULL, NULL, Setting_IsExtended, &settings.spindle.at_speed_tolerance, NULL, is_setting_available },
{ Setting_ToolChangeMode, Group_Toolchange, "Tool change mode", NULL, Format_RadioButtons, "Normal,Manual touch off,Manual touch off @ G59.3,Automatic touch off @ G59.3,Ignore M6", NULL, NULL, Setting_IsExtendedFn, set_tool_change_mode, get_int, NULL },
{ Setting_ToolChangeProbingDistance, Group_Toolchange, "Tool change probing distance", "mm", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtendedFn, set_tool_change_probing_distance, get_float, NULL },
{ Setting_ToolChangeFeedRate, Group_Toolchange, "Tool change locate feed rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtended, &settings.tool_change.feed_rate, NULL, NULL },
{ Setting_ToolChangeSeekRate, Group_Toolchange, "Tool change search seek rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtended, &settings.tool_change.seek_rate, NULL, NULL },
{ Setting_ToolChangePulloffRate, Group_Toolchange, "Tool change probe pull-off rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtended, &settings.tool_change.pulloff_rate, NULL, NULL },
{ 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 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
{ Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis,B-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL },
#elif N_AXIS > 5
{ Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis,B-Axis,C-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL },
#endif
{ Setting_AxisAutoSquareOffset, Group_Axis0, "?-axis dual axis offset", "mm", Format_Decimal, "-0.000", "-2", "2", Setting_IsExtendedFn, set_axis_setting, get_float, is_setting_available },
{ Setting_SpindleAtSpeedTolerance, Group_Spindle, "Spindle at speed tolerance", "percent", Format_Decimal, "##0.0", NULL, NULL, Setting_IsExtended, &settings.spindle.at_speed_tolerance, NULL, is_setting_available },
{ Setting_ToolChangeMode, Group_Toolchange, "Tool change mode", NULL, Format_RadioButtons, "Normal,Manual touch off,Manual touch off @ G59.3,Automatic touch off @ G59.3,Ignore M6", NULL, NULL, Setting_IsExtendedFn, set_tool_change_mode, get_int, NULL },
{ Setting_ToolChangeProbingDistance, Group_Toolchange, "Tool change probing distance", "mm", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtendedFn, set_tool_change_probing_distance, get_float, NULL },
{ Setting_ToolChangeFeedRate, Group_Toolchange, "Tool change locate feed rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtended, &settings.tool_change.feed_rate, NULL, NULL },
{ Setting_ToolChangeSeekRate, Group_Toolchange, "Tool change search seek rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtended, &settings.tool_change.seek_rate, NULL, NULL },
{ Setting_ToolChangePulloffRate, Group_Toolchange, "Tool change probe pull-off rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtended, &settings.tool_change.pulloff_rate, NULL, NULL },
{ 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 }
// { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.steppers.is_rotational.mask, NULL, NULL }
};
#ifndef NO_SETTINGS_DESCRIPTIONS
PROGMEM static const setting_descr_t setting_descr[] = {
{ Setting_PulseMicroseconds, "Sets time length per step. Minimum 2 microseconds.\\n\\n"
"This needs to be reduced from the default value of 10 when max. step rates exceed approximately 80 kHz."
},
{ Setting_StepperIdleLockTime, "Sets a short hold delay when stopping to let dynamics settle before disabling steppers. Value 255 keeps motors enabled." },
{ Setting_StepInvertMask, "Inverts the step signals (active low)." },
{ Setting_DirInvertMask, "Inverts the direction signals (active low)." },
{ Setting_InvertStepperEnable, "Inverts the stepper driver enable signals (active low). If the stepper drivers shares the same enable signal only X is used." },
{ Setting_LimitPinsInvertMask, "Inverts the axis limit input signals." },
{ Setting_InvertProbePin, "Inverts the probe input pin signal." },
{ Setting_SpindlePWMBehaviour, "" },
{ Setting_StatusReportMask, "Specifies optional data included in status reports.\\n"
"If Run substatus is enabled it may be used for simple probe protection.\\n\\n"
"Note that Parser state will be sent separately after the status report and only on changes."
},
{ Setting_JunctionDeviation, "Sets how fast Grbl travels through consecutive motions. Lower value slows it down." },
{ Setting_ArcTolerance, "Sets the G2 and G3 arc tracing accuracy based on radial error. Beware: A very small value may effect performance." },
{ Setting_ReportInches, "Enables inch units when returning any position and rate value that is not a settings value." },
{ Setting_ControlInvertMask, "Inverts the control signals (active low).\\n"
"NOTE: Block delete, Optional stop, EStop and Probe connected are optional signals, availability is driver dependent."
},
{ Setting_CoolantInvertMask, "Inverts the coolant and mist signals (active low)." },
{ Setting_SpindleInvertMask, "Inverts the spindle on, counterclockwise and PWM signals (active low)." },
{ Setting_ControlPullUpDisableMask, "Disable the control signals pullup resistors. Potentially enables pulldown resistor if available.\\n"
"NOTE: Block delete, Optional stop and EStop are optional signals, availability is driver dependent."
},
{ Setting_LimitPullUpDisableMask, "Disable the limit signals pullup resistors. Potentially enables pulldown resistor if available."},
{ Setting_ProbePullUpDisable, "Disable the probe signal pullup resistor. Potentially enables pulldown resistor if available." },
{ Setting_SoftLimitsEnable, "Enables soft limits checks within machine travel and sets alarm when exceeded. Requires homing." },
{ Setting_HardLimitsEnable, "When enabled immediately halts motion and throws an alarm when a limit switch is triggered. In strict mode only homing is possible when a switch is engaged." },
{ Setting_HomingEnable, "Enables homing cycle. Requires limit switches on axes to be automatically homed.\\n\\n"
"When `Enable single axis commands` is checked, single axis homing can be performed by $H<axis letter> commands.\\n\\n"
"When `Allow manual` is checked, axes not homed automatically may be homed manually by $H or $H<axis letter> commands.\\n\\n"
"`Override locks` is for allowing a soft reset to disable `Homing on startup required`."
},
{ Setting_HomingDirMask, "Homing searches for a switch in the positive direction. Set axis bit to search in negative direction." },
{ Setting_HomingFeedRate, "Feed rate to slowly engage limit switch to determine its location accurately." },
{ Setting_HomingSeekRate, "Seek rate to quickly find the limit switch before the slower locating phase." },
{ Setting_HomingDebounceDelay, "Sets a short delay between phases of homing cycle to let a switch debounce." },
{ Setting_HomingPulloff, "Retract distance after triggering switch to disengage it. Homing will fail if switch isn't cleared." },
{ Setting_G73Retract, "G73 retract distance (for chip breaking drilling)." },
{ Setting_PulseDelayMicroseconds, "Step pulse delay.\\n\\n"
"Normally leave this at 0 as there is an implicit delay on direction changes when AMASS is active."
},
{ Setting_RpmMax, "Maximum spindle speed. Sets PWM to maximum duty cycle." },
{ Setting_RpmMin, "Minimum spindle speed. Sets PWM to minimum duty cycle." },
{ Setting_Mode, "Laser mode: consecutive G1/2/3 commands will not halt when spindle speed is changed.\\n"
"Lathe mode: allows use of G7, G8, G96 and G97."
},
{ Setting_PWMFreq, "Spindle PWM frequency." },
{ Setting_PWMOffValue, "Spindle PWM off value in percent (duty cycle)." },
{ Setting_PWMMinValue, "Spindle PWM min value in percent (duty cycle)." },
{ Setting_PWMMaxValue, "Spindle PWM max value in percent (duty cycle)." },
{ Setting_StepperDeenergizeMask, "Specifies which steppers not to disable when stopped." },
{ Setting_SpindlePPR, "Spindle encoder pulses per revolution." },
{ Setting_EnableLegacyRTCommands, "Enables \"normal\" processing of ?, ! and ~ characters when part of $-setting or comment. If disabled then they are added to the input string instead." },
{ Setting_JogSoftLimited, "Limit jog commands to machine limits for homed axes." },
{ Setting_ParkingEnable, "Enables parking cycle, requires parking axis homed." },
{ Setting_ParkingAxis, "Define which axis that performs the parking motion." },
{ Setting_HomingLocateCycles, "Number of homing passes. Minimum 1, maximum 128." },
{ Setting_HomingCycle_1, "Axes to home in first pass." },
{ Setting_HomingCycle_2, "Axes to home in second pass." },
{ Setting_HomingCycle_3, "Axes to home in third pass." },
#ifdef A_AXIS
{ Setting_HomingCycle_4, "Axes to home in fourth pass." },
#endif
#ifdef B_AXIS
{ Setting_HomingCycle_5, "Axes to home in fifth pass." },
#endif
#ifdef C_AXIS
{ Setting_HomingCycle_6, "Axes to home in sixth pass." },
#endif
{ Setting_JogStepSpeed, "Step jogging speed in millimeters per minute." },
{ Setting_JogSlowSpeed, "Slow jogging speed in millimeters per minute." },
{ Setting_JogFastSpeed, "Fast jogging speed in millimeters per minute." },
{ Setting_JogStepDistance, "Jog distance for single step jogging." },
{ Setting_JogSlowDistance, "Jog distance before automatic stop." },
{ Setting_JogFastDistance, "Jog distance before automatic stop." },
#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
{ Setting_ParkingPulloutIncrement, "Spindle pull-out and plunge distance in mm.Incremental distance." },
{ Setting_ParkingPulloutRate, "Spindle pull-out/plunge slow feed rate in mm/min." },
{ Setting_ParkingTarget, "Parking axis target. In mm, as machine coordinate [-max_travel, 0]." },
{ Setting_ParkingFastRate, "Parking fast rate to target after pull-out in mm/min." },
{ Setting_RestoreOverrides, "Restore overrides to default values at program end." },
{ Setting_DoorOptions, "Enable this if it is desirable to open the safety door when in IDLE mode (eg. for jogging)." },
#endif
{ Setting_SleepEnable, "Enable sleep mode." },
{ Setting_HoldActions, "Actions taken during feed hold and on resume from feed hold." },
{ Setting_ForceInitAlarm, "Starts Grbl in alarm mode after a cold reset." },
{ Setting_ProbingFeedOverride, "Allow feed override during probing." },
{ Setting_SpindlePGain, "" },
{ Setting_SpindleIGain, "" },
{ Setting_SpindleDGain, "" },
{ Setting_SpindleMaxError, "" },
{ Setting_SpindleIMaxError, "Spindle PID max integrator error." },
{ Setting_PositionPGain, "" },
{ Setting_PositionIGain, "" },
{ Setting_PositionDGain, "" },
{ Setting_PositionIMaxError, "Spindle sync PID max integrator error." },
{ Setting_AxisStepsPerMM, "Axis travel resolution in steps per millimeter." },
{ Setting_AxisMaxRate, "Axis maximum rate. Used as G0 rapid rate." },
{ Setting_AxisAcceleration, "Axis acceleration. Used for motion planning to not exceed motor torque and lose steps." },
{ Setting_AxisMaxTravel, "Maximum axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances." },
#ifdef ENABLE_BACKLASH_COMPENSATION
{ Setting_AxisBacklash, "Axis backlash distance to compensate for." },
#endif
{ Setting_AxisAutoSquareOffset, "Axis offset between sides to compensate for homing switches inaccuracies." },
{ Setting_SpindleAtSpeedTolerance, "Spindle at speed" },
{ Setting_ToolChangeMode, "Normal: allows jogging for manual touch off. Set new position manually.\\n\\n"
"Manual touch off: retracts tool axis to home position for tool change, use jogging or $TPW for touch off.\\n\\n"
"Manual touch off @ G59.3: retracts tool axis to home position then to G59.3 position for tool change, use jogging or $TPW for touch off.\\n\\n"
"Automatic touch off @ G59.3: retracts tool axis to home position for tool change, then to G59.3 position for automatic touch off.\\n\\n"
"All modes except \"Normal\" and \"Ignore M6\" returns the tool (controlled point) to original position after touch off."
},
{ Setting_ToolChangeProbingDistance, "Maximum probing distance for automatic or $TPW touch off." },
{ Setting_ToolChangeFeedRate, "Feed rate to slowly engage tool change sensor to determine the tool offset accurately." },
{ Setting_ToolChangeSeekRate, "Seek rate to quickly find the tool change sensor before the slower locating phase." },
{ 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." }
};
#endif
static setting_details_t details = {
.groups = setting_group_detail,
.n_groups = sizeof(setting_group_detail) / sizeof(setting_group_detail_t),
.settings = setting_detail,
.n_settings = sizeof(setting_detail) / sizeof(setting_detail_t),
#ifndef NO_SETTINGS_DESCRIPTIONS
.descriptions = setting_descr,
.n_descriptions = sizeof(setting_descr) / sizeof(setting_descr_t),
#endif
.save = settings_write_global
};
@@ -797,6 +939,15 @@ static status_code_t set_tool_change_probing_distance (setting_id_t id, float va
return Status_OK;
}
#if N_AXIS > 3
static status_code_t set_rotational_axes (setting_id_t id, uint_fast16_t int_value)
{
settings.steppers.is_rotational.mask = (int_value << 3) & AXES_BITMASK;
return Status_OK;
}
#endif
#ifdef ENABLE_SPINDLE_LINEARIZATION
static status_code_t set_linear_piece (setting_id_t id, char *svalue)
@@ -1080,6 +1231,12 @@ static uint32_t get_int (setting_id_t id)
value = settings.tool_change.mode;
break;
#if N_AXIS > 3
case Settings_Axis_Rotational:
value = (settings.steppers.is_rotational.mask & AXES_BITMASK) >> 3;
break;
#endif
default:
break;
}
@@ -1169,7 +1326,7 @@ static bool is_setting_available (const setting_detail_t *setting)
{
bool available = false; // settings_is_group_available(setting->group);
switch(normalize_id(setting->id)) {
if(setting) switch(normalize_id(setting->id)) {
case Setting_SpindlePWMBehaviour:
available = hal.driver_cap.variable_spindle;
+16 -1
View File
@@ -30,7 +30,11 @@
// 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
#if N_AXIS > 3 // TODO: remove on next version update
#define SETTINGS_VERSION 20 // NOTE: Check settings_reset() when moving to next version.
#else
#define SETTINGS_VERSION 19 // NOTE: Check settings_reset() when moving to next version.
#endif
// Define axis settings numbering scheme. Starts at Setting_AxisSettingsBase, every INCREMENT, over N_SETTINGS.
#define AXIS_SETTINGS_INCREMENT 10 // Must be greater than the number of axis settings.
@@ -449,7 +453,9 @@ typedef struct {
axes_signals_t dir_invert;
axes_signals_t enable_invert;
axes_signals_t deenergize;
// axes_signals_t is_rotational; or add to axis_settings_t below as bitmap union? rotational axes are not scaled in imperial mode
#if N_AXIS > 3
axes_signals_t is_rotational; // rotational axes are not scaled in imperial mode
#endif
float pulse_microseconds;
float pulse_delay_microseconds;
uint16_t idle_lock_time; // If value = 255, steppers do not disable.
@@ -660,6 +666,11 @@ typedef struct setting_detail {
bool (*is_available)(const struct setting_detail *setting);
} setting_detail_t;
typedef struct {
setting_id_t id;
const char *description;
} setting_descr_t;
typedef status_code_t (*setting_set_int_ptr)(setting_id_t id, uint_fast16_t value);
typedef status_code_t (*setting_set_float_ptr)(setting_id_t id, float value);
typedef status_code_t (*setting_set_string_ptr)(setting_id_t id, char *value);
@@ -682,6 +693,10 @@ typedef struct setting_details {
const setting_group_detail_t *groups;
const uint16_t n_settings;
const setting_detail_t *settings;
#ifndef NO_SETTINGS_DESCRIPTIONS
const uint16_t n_descriptions;
const setting_descr_t *descriptions;
#endif
struct setting_details *(*on_get_settings)(void);
settings_changed_ptr on_changed;
driver_settings_save_ptr save;
+10
View File
@@ -35,6 +35,16 @@ typedef struct {
static stream_state_t stream = {0};
// called from stream drivers while tx is blocking, returns false to terminate
bool stream_tx_blocking (void)
{
// TODO: Restructure st_prep_buffer() calls to be executed here during a long print.
grbl.on_execute_realtime(state_get());
return !(sys.rt_exec_state & EXEC_RESET);
}
// "dummy" version of serialGetC
int16_t stream_get_null (void)
{
+2
View File
@@ -255,6 +255,8 @@ bool stream_enable_mpg (const io_stream_t *mpg_stream, bool mpg_mode);
bool stream_buffer_all (char c);
bool stream_tx_blocking (void);
#ifdef DEBUGOUT
void debug_stream_init (io_stream_t *stream);
#endif
+81 -43
View File
@@ -39,9 +39,14 @@ static status_code_t enumerate_errors (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);
static status_code_t enumerate_settings_grblformatted (sys_state_t state, char *args);
static status_code_t enumerate_settings_halformatted (sys_state_t state, char *args);
static status_code_t enumerate_pins (sys_state_t state, char *args);
static status_code_t output_settings (sys_state_t state, char *args);
static status_code_t output_all_settings (sys_state_t state, char *args);
#ifndef NO_SETTINGS_DESCRIPTIONS
static status_code_t output_setting_description (sys_state_t state, char *args);
#endif
static status_code_t output_parser_state (sys_state_t state, char *args);
static status_code_t toggle_block_delete (sys_state_t state, char *args);
static status_code_t toggle_single_block (sys_state_t state, char *args);
@@ -168,52 +173,57 @@ 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_settings},
{"+", false, output_all_settings},
{"B", true, toggle_block_delete},
{"S", true, toggle_single_block},
{"O", true, toggle_optional_stop},
{"C", true, check_mode},
{"X", false, disable_lock},
{"H", false, home},
{"HX", false, home_x},
{"HY", false, home_y},
{"HZ", false, home_z},
{ "G", true, output_parser_state },
{ "J", false, jog },
{ "#", true, output_ngc_parameters },
{ "$", false, output_settings },
{ "+", false, output_all_settings },
#ifndef NO_SETTINGS_DESCRIPTIONS
{ "SED", false, output_setting_description },
#endif
{ "B", true, toggle_block_delete },
{ "S", true, toggle_single_block },
{ "O", true, toggle_optional_stop },
{ "C", true, check_mode },
{ "X", false, disable_lock },
{ "H", false, home },
{ "HX", false, home_x },
{ "HY", false, home_y },
{ "HZ", false, home_z },
#ifdef A_AXIS
{"HA", false, home_a},
{ "HA", false, home_a },
#endif
#ifdef B_AXIS
{"HB", false, home_b},
{ "HB", false, home_b },
#endif
#ifdef C_AXIS
{"HC", false, home_c},
{ "HC", false, home_c },
#endif
{"HELP", false, output_help},
{"SLP", true, enter_sleep},
{"TLR", true, set_tool_reference},
{"TPW", true, tool_probe_workpiece},
{"I", false, build_info},
{"I+", true, output_all_build_info},
{"RST", false, settings_reset},
{"N", true, output_startup_lines},
{"N0", false, set_startup_line0},
{"N1", false, set_startup_line1},
{"EA", true, enumerate_alarms},
{"EE", true, enumerate_errors},
{"EG", true, enumerate_groups},
{"ES", true, enumerate_settings},
{"E*", true, enumerate_all},
{"PINS", true, enumerate_pins},
{"RST", false, settings_reset},
{"LEV", true, report_last_signals_event},
{"LIM", true, report_current_limit_state},
{"SD", false, report_spindle_data},
{"SR", false, spindle_reset_data},
{ "HELP", false, output_help },
{ "SLP", true, enter_sleep },
{ "TLR", true, set_tool_reference },
{ "TPW", true, tool_probe_workpiece },
{ "I", false, build_info },
{ "I+", true, output_all_build_info },
{ "RST", false, settings_reset },
{ "N", true, output_startup_lines },
{ "N0", false, set_startup_line0 },
{ "N1", false, set_startup_line1 },
{ "EA", true, enumerate_alarms },
{ "EE", true, enumerate_errors },
{ "EG", true, enumerate_groups },
{ "ES", true, enumerate_settings },
{ "ESG", true, enumerate_settings_grblformatted },
{ "ESH", true, enumerate_settings_halformatted },
{ "E*", true, enumerate_all },
{ "PINS", true, enumerate_pins },
{ "RST", false, settings_reset },
{ "LEV", true, report_last_signals_event },
{ "LIM", true, report_current_limit_state },
{ "SD", false, report_spindle_data },
{ "SR", false, spindle_reset_data },
#ifdef DEBUGOUT
{"Q", true, output_memmap},
{ "Q", true, output_memmap },
#endif
};
@@ -345,7 +355,17 @@ static status_code_t enumerate_groups (sys_state_t state, char *args)
static status_code_t enumerate_settings (sys_state_t state, char *args)
{
return report_settings_details(false, Setting_SettingsAll, Group_All);
return report_settings_details(SettingsFormat_MachineReadable, Setting_SettingsAll, Group_All);
}
static status_code_t enumerate_settings_grblformatted (sys_state_t state, char *args)
{
return report_settings_details(SettingsFormat_Grbl, Setting_SettingsAll, Group_All);
}
static status_code_t enumerate_settings_halformatted (sys_state_t state, char *args)
{
return report_settings_details(SettingsFormat_grblHAL, Setting_SettingsAll, Group_All);
}
static status_code_t enumerate_all (sys_state_t state, char *args)
@@ -353,7 +373,7 @@ static status_code_t enumerate_all (sys_state_t state, char *args)
report_alarm_details();
report_error_details();
report_setting_group_details(true, NULL);
return report_settings_details(false, Setting_SettingsAll, Group_All);
return report_settings_details(SettingsFormat_MachineReadable, Setting_SettingsAll, Group_All);
}
static status_code_t enumerate_pins (sys_state_t state, char *args)
@@ -369,7 +389,7 @@ static status_code_t output_settings (sys_state_t state, char *args)
int32_t id;
retval = read_int(args, &id);
if(retval == Status_OK && id >= 0)
retval = report_settings_details(true, (setting_id_t)id, Group_All);
retval = report_settings_details(SettingsFormat_HumanReadable, (setting_id_t)id, Group_All);
} else if (state & (STATE_CYCLE|STATE_HOLD))
retval = Status_IdleError; // Block during cycle. Takes too long to print.
else
@@ -382,6 +402,24 @@ static status_code_t output_settings (sys_state_t state, char *args)
return retval;
}
#ifndef NO_SETTINGS_DESCRIPTIONS
static status_code_t output_setting_description (sys_state_t state, char *args)
{
status_code_t retval = Status_BadNumberFormat;
if(args) {
int32_t id;
retval = read_int(args, &id);
if(retval == Status_OK && id >= 0)
retval = report_setting_description(SettingsFormat_MachineReadable, (setting_id_t)id);
}
return retval;
}
#endif
static status_code_t output_all_settings (sys_state_t state, char *args)
{
status_code_t retval = Status_OK;
@@ -390,7 +428,7 @@ static status_code_t output_all_settings (sys_state_t state, char *args)
int32_t id;
retval = read_int(args, &id);
if(retval == Status_OK && id >= 0)
retval = report_settings_details(true, (setting_id_t)id, Group_All);
retval = report_settings_details(SettingsFormat_HumanReadable, (setting_id_t)id, Group_All);
} else if (state & (STATE_CYCLE|STATE_HOLD))
retval = Status_IdleError; // Block during cycle. Takes too long to print.
else