Moved compile time option ROTARY_FIX to setting $701 with option for

reverting imperial to metric conversion for angular moves.
Ref. PR#979 and discussion #241.
Added hooks for future G33.1 rigid tapping cycle implementation.
Added lathe tool parameters front angle, back angle and orientation
to tool data when lathe UVW option is enabled. Currently unused.
This commit is contained in:
Terje Io
2026-08-11 08:15:08 +02:00
parent 5848a84179
commit 6523e08de8
16 changed files with 257 additions and 53 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
## grblHAL ##
Latest build date is 20260803, see the [changelog](changelog.md) for details.
Latest build date is 20260811, see the [changelog](changelog.md) for details.
> [!NOTE]
> A settings reset will be performed on an update of builds prior to 20241208. Backup and restore of settings is recommended.
+21 -2
View File
@@ -1,6 +1,25 @@
## grblHAL changelog
<a name="20260729">Build 20260803
<a name="20260811">Build 20260811
Core:
* Moved compile time option `ROTARY_FIX` to setting `$701` with option for reverting imperial to metric conversion for angular moves.
Ref. PR[#979](https://github.com/grblHAL/core/pull/979) and discussion [#241](https://github.com/grblHAL/core/discussions/241).
* Added hooks for future G33.1 rigid tapping cycle implementation.
* Added lathe tool parameters front angle, back angle and orientation to tool data when lathe UVW option is enabled. Currently unused.
> [!NOTE]
> If updating from a version where lathe UVW option is enabled settings and NVS \(flash or EEPROM\) based tooltable will be reset. Backup and restore.
Plugins:
* Misc, tooltable: updated to handle lathe tool parameters when enabled. "Hardened" code.
---
<a name="20260703">Build 20260803
Core:
@@ -14,7 +33,7 @@ Drivers:
* iMXRT1062: fix for SD card early mount messing with spindle pins. Ref. issue [#111](https://github.com/grblHAL/iMXRT1062/issues/111).
* Simulator: updated Web Builder cmake file, ref [#23](https://github.com/grblHAL/Simulator/issues/23).
* Simulator: updated Web Builder cmake file, ref. [#23](https://github.com/grblHAL/Simulator/issues/23).
Plugins:
+9
View File
@@ -2071,6 +2071,15 @@ For the controller the distance is unitless and and can be in degrees, radians,
#endif
///@}
/*! @name $701 - Setting_RotaryOptions
When enabled feed rate for combined rotary and linear motion is converted to inverse time mode..
*/
///@{
#if !defined DEFAULT_ROTARY_FIX_ENABLE || defined __DOXYGEN__
#define DEFAULT_ROTARY_FIX_ENABLE Off
#endif
///@}
/*! @name $680 - Setting_StepperEnableDelay
Allowed range 0 - 250 milliseconds. Driver adds ~2 milliseconds.
*/
+67 -15
View File
@@ -1497,15 +1497,15 @@ status_code_t gc_execute_block (char *block)
break;
case 33: case 76:
if(mantissa != 0)
RETURN(Status_GcodeUnsupportedCommand); // [G33.1 not yet supported]
if (axis_command)
if(axis_command)
RETURN(Status_GcodeAxisCommandConflict); // [Axis word/command conflict]
axis_command = AxisCommand_MotionMode;
word_bit.modal_group.G1 = On;
gc_block.modal.motion = (motion_mode_t)int_value;
// if(mantissa == 10)
// gc_block.modal.motion = MotionMode_RigidTapping;
if(mantissa == 10) {
mantissa = 0;
gc_block.modal.motion = MotionMode_RigidTapping;
}
gc_block.modal.canned_cycle_active = false;
break;
@@ -2376,6 +2376,12 @@ status_code_t gc_execute_block (char *block)
gc_block.words.k = Off;
gc_block.values.k = gc_block.modal.units_imperial ? gc_block.values.ijk[K_VALUE] *= MM_PER_INCH : gc_block.values.ijk[K_VALUE];
}
if(gc_block.modal.motion == MotionMode_RigidTapping) {
if(!gc_block.words.i)
gc_block.values.ijk[I_VALUE] = 1.0f; // RPM multiplier
else
gc_block.words.i = Off;
}
}
// bit_false(gc_block.words,bit(Word_F)); // NOTE: Single-meaning value word. Set at end of error-checking.
@@ -2968,18 +2974,31 @@ status_code_t gc_execute_block (char *block)
if((tool_data = grbl.tool_table.get_tool((tool_id_t)p_value)->data) == NULL)
RETURN(Status_GcodeIllegalToolTableEntry); // [Greater than max allowed tool number or not in tool table]
#if LATHE_UVW_OPTION
if(gc_block.words.q) {
if(!isintf(gc_block.values.q) || gc_block.values.q < 0.0f || gc_block.values.q > 9.0f)
RETURN(Status_GcodeValueOutOfRange); // [Illegal orientation]
tool_data->orientation = (tool_orientation_t)gc_block.values.q;
gc_block.words.q = Off;
}
if(gc_block.words.i) {
tool_data->front_angle = gc_block.values.ijk[I_VALUE];
gc_block.words.i = Off;
}
if(gc_block.words.j) {
tool_data->back_angle = gc_block.values.ijk[J_VALUE];
gc_block.words.j = Off;
}
#endif
if(gc_block.words.r) {
tool_data->radius = gc_block.values.r;
gc_block.words.r = Off;
}
#if COMPATIBILITY_LEVEL <= 1
coord_system_data_t g59_3_offset;
if(gc_block.values.l == 11 && !settings_read_coord_data(CoordinateSystem_G59_3, &g59_3_offset))
RETURN(Status_SettingReadFail);
#endif
idx = N_AXIS;
do {
if(bit_istrue(axis_words.mask, bit(--idx))) {
@@ -3190,7 +3209,7 @@ status_code_t gc_execute_block (char *block)
RETURN(Status_GcodeSpindleNotRunning);
// Check if feed rate is defined for the motion modes that require it.
if(gc_block.modal.motion == MotionMode_SpindleSynchronized) {
if(gc_block.modal.motion == MotionMode_SpindleSynchronized || gc_block.modal.motion == MotionMode_RigidTapping) {
if(!sspindle->hal->get_data)
RETURN(Status_GcodeUnsupportedCommand); // [G33, G33.1]
@@ -4538,6 +4557,35 @@ status_code_t gc_execute_block (char *block)
}
break;
case MotionMode_RigidTapping:
{
status_code_t status;
gc_override_flags_t overrides = sys.override.control; // Save current override disable status.
protocol_buffer_synchronize(); // Wait until any previous moves are finished.
if((status = init_sync_motion(&plan_data, gc_block.values.k)) == Status_OK)
status = mc_rigid_tapping(&plan_data, (coord_data_t *)gc_block.values.xyz, (coord_data_t *)gc_state.position, gc_block.values.k, gc_block.values.ijk[I_VALUE]);
// if(status != Status_GcodeUnsupportedCommand)
mc_override_ctrl_update(overrides); // Wait until synchronized move is finished, then restore previous override disable status.
#if NGC_PARAMETERS_ENABLE
if(status != Status_GcodeUnsupportedCommand) {
if(!ngc_call_push(&gc_state + ngc_call_level()))
RETURN(Status_FlowControlStackOverflow); // [Call level too deep]
#ifdef A_AXIS
parameter_words_t g33_1_words = (parameter_words_t){ .i = On, .k = On, .x = axis_words.x, .y = axis_words.y, .z = axis_words.z, .a = axis_words.a };
#else
parameter_words_t g33_1_words = (parameter_words_t){ .i = On, .k = On, .x = axis_words.x, .y = axis_words.y, .z = axis_words.z };
#endif
g33_1_words.mask = macro_arguments_push(&gc_block.values, g33_1_words, NULL).mask;
RETURN(macro_call(331, (line_number_t)gc_block.values.n, g33_1_words, 1));
}
#endif
}
break;
case MotionMode_Threading:
{
protocol_buffer_synchronize(); // Wait until any previous moves are finished.
@@ -4562,9 +4610,11 @@ status_code_t gc_execute_block (char *block)
.motion = gc_block.modal.motion,
.x = gc_block.values.xyz[X_AXIS],
.z = gc_block.values.xyz[Z_AXIS],
.start_distance = gc_block.values.d,
.remaining_distance = gc_block.values.e,
.passes = gc_block.values.p
.finish = {
.start_distance = gc_block.values.d,
.end_distance = gc_block.values.e,
.passes = gc_block.values.p
}
};
RETURN(lathe_cycle(&plan_data, (coord_data_t *)gc_state.position, (uint32_t)gc_block.values.q, &args));
}
@@ -4581,9 +4631,11 @@ status_code_t gc_execute_block (char *block)
.motion = gc_block.modal.motion,
.x = gc_block.values.xyz[X_AXIS],
.z = gc_block.values.xyz[Z_AXIS],
.increment = gc_block.values.ijk[0],
.retract_distance = gc_block.values.r,
.remaining_distance = gc_block.values.d
.rough = {
.increment = gc_block.values.ijk[0],
.retract_distance = gc_block.values.r,
.remaining_distance = gc_block.values.d
}
};
RETURN(lathe_cycle(&plan_data, (coord_data_t *)gc_state.position, (uint32_t)gc_block.values.q, &args));
}
+25 -2
View File
@@ -589,11 +589,34 @@ typedef struct {
gc_taper_type end_taper_type;
} gc_thread_data;
#if LATHE_UVW_OPTION
//! Lathe tool orientation.
typedef enum {
ToolPos_Undefined = 0,
ToolPos1_135,
ToolPos2_45,
ToolPos3_315,
ToolPos4_225,
ToolPos5_180,
ToolPos6_90,
ToolPos7_0,
ToolPos8_270,
ToolPos9_Down,
} tool_orientation_t;
#endif
//! Tool data.
typedef struct {
coord_data_t offset; //!< Tool offset
float radius; //!< Radius of tool (currently unsupported)
tool_id_t tool_id; //!< Tool number
#if LATHE_UVW_OPTION
float front_angle;
float back_angle;
tool_orientation_t orientation;
#endif
} tool_data_t;
//! Tool table entry.
@@ -636,12 +659,12 @@ typedef struct {
float start_distance;
float end_distance;
float passes;
};
} finish;
struct { // G71.x & G72.x
float retract_distance;
float remaining_distance;
float increment;
};
} rough;
};
} lathe_cycle_arguments_t;
+1 -1
View File
@@ -42,7 +42,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_BUILD 20260803
#define GRBL_BUILD 20260811
#define GRBL_URL "https://github.com/grblHAL"
+5
View File
@@ -803,6 +803,11 @@ FLASHMEM status_code_t lathe_cycle (plan_line_data_t *pl_data, coord_data_t *pos
#endif
FLASHMEM status_code_t mc_rigid_tapping (plan_line_data_t *pl_data, coord_data_t *target, coord_data_t *position, float pitch, float rpm_multiplier)
{
return Status_GcodeUnsupportedCommand; // TBC
}
// Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog.
FLASHMEM status_code_t mc_jog_execute (plan_line_data_t *pl_data, parser_block_t *gc_block, float *position)
{
+2
View File
@@ -55,6 +55,8 @@ void mc_thread (plan_line_data_t *pl_data, float *position, gc_thread_data *thre
status_code_t lathe_cycle (plan_line_data_t *pl_data, coord_data_t *position, uint32_t o_label, lathe_cycle_arguments_t *args);
#endif
status_code_t mc_rigid_tapping (plan_line_data_t *pl_data, coord_data_t *target, coord_data_t *position, float pitch, float rpm_multiplier);
// Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog.
status_code_t mc_jog_execute(plan_line_data_t *pl_data, parser_block_t *gc_block, float *position);
+30
View File
@@ -220,6 +220,30 @@ FLASHMEM static float tool_offset (ngc_param_id_t id)
return axis <= 9 ? gc_state.modal.tool_length_offset[axis] : 0.0f;
}
FLASHMEM static float tool_diameter (ngc_param_id_t id)
{
return gc_state.tool->radius * 2.0f;
}
#if LATHE_UVW_OPTION
FLASHMEM static float tool_front_angle (ngc_param_id_t id)
{
return gc_state.tool->front_angle;
}
FLASHMEM static float tool_back_angle (ngc_param_id_t id)
{
return gc_state.tool->back_angle;
}
FLASHMEM static float tool_orientation (ngc_param_id_t id)
{
return (float)gc_state.tool->orientation;
}
#endif
FLASHMEM static float g28_home (ngc_param_id_t id)
{
float value = 0.0f;
@@ -318,6 +342,12 @@ PROGMEM static const ngc_ro_param_t ngc_ro_params[] = {
{ .id_min = 5399, .id_max = 5399, .get = m66_result }, // LinuxCNC
{ .id_min = 5400, .id_max = 5400, .get = tool_number }, // LinuxCNC
{ .id_min = 5401, .id_max = 5409, .get = tool_offset }, // LinuxCNC
{ .id_min = 5410, .id_max = 5410, .get = tool_diameter }, // LinuxCNC
#if LATHE_UVW_OPTION
{ .id_min = 5411, .id_max = 5411, .get = tool_front_angle }, // LinuxCNC
{ .id_min = 5412, .id_max = 5412, .get = tool_back_angle }, // LinuxCNC
{ .id_min = 5413, .id_max = 5413, .get = tool_orientation }, // LinuxCNC
#endif
{ .id_min = 5420, .id_max = 5428, .get = work_position }, // LinuxCNC
{ .id_min = 5599, .id_max = 5599, .get = debug_output } // LinuxCNC
};
+19
View File
@@ -360,8 +360,21 @@ typedef union {
float x;
float y;
};
struct {
float z;
float x;
} g18;
/* struct {
float y;
float z;
} g19; */
} point_2d_t;
typedef struct {
point_2d_t min;
point_2d_t max;
} bbox_2d_t;
typedef union {
float values[3];
struct {
@@ -371,6 +384,11 @@ typedef union {
};
} point_3d_t;
typedef struct {
point_3d_t min;
point_3d_t max;
} bbox_3d_t;
//! Axis index to plane assignment.
typedef union {
uint8_t axis[3];
@@ -532,4 +550,5 @@ static int ffs (int i)
#endif // _WIN32
#endif
+27 -25
View File
@@ -31,10 +31,6 @@
#include "planner.h"
#include "protocol.h"
#ifndef ROTARY_FIX
#define ROTARY_FIX 0
#endif
#if ENABLE_BACKLASH_COMPENSATION
void mc_sync_backlash_position (void);
#endif
@@ -409,7 +405,7 @@ bool plan_buffer_line (float *target, plan_line_data_t *pl_data)
int32_t target_steps[N_AXIS], position_steps[N_AXIS], delta_steps;
uint_fast8_t idx;
float unit_vec[N_AXIS];
#if N_AXIS > 3 && ROTARY_FIX
#if N_AXIS > 3
axes_signals_t motion = {0};
#endif
@@ -450,7 +446,7 @@ bool plan_buffer_line (float *target, plan_line_data_t *pl_data)
direction.bits |= bit(idx);
else
direction.bits &= ~bit(idx);
#if N_AXIS > 3 && ROTARY_FIX
#if N_AXIS > 3
motion.mask |= bit(idx);
#endif
} else {
@@ -489,41 +485,47 @@ bool plan_buffer_line (float *target, plan_line_data_t *pl_data)
pl_data->output_commands = NULL; // Indicate commands are already queued for execution
}
#if N_AXIS > 3 && ROTARY_FIX
#if N_AXIS > 3
// NIST RS274 (2.1.2.5 A & 2.1.2.6) states that G94 linear motion with simultaneous angular motion
// has the feedrate assigned to the linear axes. To accomplish this we'll change the planner block to
// behave as if its doing a G93 inverse time mode move.
if(!block->condition.inverse_time &&
!block->condition.rapid_motion &&
(motion.mask & settings.steppers.is_rotary.mask) &&
(motion.mask & ~settings.steppers.is_rotary.mask)) {
if(settings.flags.rotary_fix_enable &&
!block->condition.inverse_time &&
!block->condition.rapid_motion &&
(motion.mask & settings.steppers.is_rotary.mask)) {
float linear_magnitude = 0.0f;
if(motion.mask & ~settings.steppers.is_rotary.mask) {
idx = 0;
motion.mask &= ~settings.steppers.is_rotary.mask;
float linear_magnitude = 0.0f;
while(motion.mask) {
if(motion.mask & 0x01)
linear_magnitude += unit_vec[idx] * unit_vec[idx];
motion.mask >>= 1;
idx++;
}
idx = 0;
motion.mask &= ~settings.steppers.is_rotary.mask;
pl_data->feed_rate = 1.0f / (sqrtf(linear_magnitude) / pl_data->feed_rate);
while(motion.mask) {
if(motion.mask & 0x01)
linear_magnitude += unit_vec[idx] * unit_vec[idx];
motion.mask >>= 1;
idx++;
}
block->condition.inverse_time = On;
pl_data->feed_rate = 1.0f / (sqrtf(linear_magnitude) / pl_data->feed_rate);
block->condition.inverse_time = On;
} else if(gc_state.modal.units_imperial && settings.flags.revert_metric_conversion)
pl_data->feed_rate /= 25.4f;// Revert in/min to mm/min conversion for angular motion
}
#endif
// Calculate the unit vector of the line move and the block maximum feed rate and acceleration scaled
// down such that no individual axes maximum values are exceeded with respect to the line direction.
#if N_AXIS > 3 && ROTARY_FIX
// NOTE: This calculation assumes all block motion axes are orthogonal (Cartesian), and if also rotational, then
// motion mode must be inverse time mode. Operates on the absolute value of the unit vector.
#if N_AXIS > 3
// NOTE: This calculation assumes all block motion axes are orthogonal (Cartesian), and if also rotational
// and settings.flags.rotary_fix_enable, then motion mode must be inverse time mode.
// Operates on the absolute value of the unit vector.
#else
// NOTE: This calculation assumes all axes are orthogonal (Cartesian) and works with ABC-axes,
// if they are also orthogonal/independent. Operates on the absolute value of the unit vector.
+5
View File
@@ -268,6 +268,11 @@
spindle_interlock_init();
#endif
#if VIRTUAL_INPUTS_ENABLE
extern void virtual_inputs_init (void);
virtual_inputs_init();
#endif
// End third party plugin definitions.
#if ODOMETER_ENABLE
+9 -4
View File
@@ -1001,6 +1001,11 @@ FLASHMEM void report_build_info (char *line, bool extended)
strcat(buf, "PC,");
}
#if N_AXIS > 3
if(settings.flags.rotary_fix_enable)
strcat(buf, "RF,");
#endif
if(hal.signals_cap.stop_disable)
strcat(buf, "OS,");
@@ -1026,9 +1031,9 @@ FLASHMEM void report_build_info (char *line, bool extended)
if(hal.reboot)
strcat(buf, "REBOOT,");
#if NGC_EXPRESSIONS_ENABLE
#if NGC_EXPRESSIONS_ENABLE
strcat(buf, "EXPR,");
#endif
#endif
if(atc != ATC_None || (settings.tool_change.mode != ToolChange_Ignore && !!hal.stream.suspend_read))
strcat(buf, atc == ATC_None ? "TC," : (atc == ATC_Online ? "ATC=1," : "ATC=0,")); // Tool change supported (M6)
@@ -1044,9 +1049,9 @@ FLASHMEM void report_build_info (char *line, bool extended)
if(canbus_enabled())
strcat(buf, "CAN,");
#ifdef PID_LOG
#ifdef PID_LOG
strcat(buf, "PID,");
#endif
#endif
append = &buf[strlen(buf) - 1];
if(*append == ',')
+31 -1
View File
@@ -96,6 +96,11 @@ PROGMEM static const settings_t defaults = {
.flags.keep_rapids_override_on_reset = DEFAULT_KEEP_RAPIDS_OVR_ON_RESET,
.flags.keep_feed_override_on_reset = DEFAULT_KEEP_FEED_OVR_ON_RESET,
.flags.tool_persistent = DEFAULT_PERSIST_TOOL,
#if defined(ROTARY_FIX) // for backwards compatibility
.flags.rotary_fix_enable = On,
#else
.flags.rotary_fix_enable = DEFAULT_ROTARY_FIX_ENABLE,
#endif
.probe.disable_probe_pullup = DEFAULT_PROBE_SIGNAL_DISABLE_PULLUP,
.probe.allow_feed_override = DEFAULT_ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES,
@@ -1198,6 +1203,18 @@ static status_code_t set_homing_enable (setting_id_t id, uint_fast16_t int_value
return Status_OK;
}
#if N_AXIS > 3
static status_code_t set_rotary_options (setting_id_t id, uint_fast16_t int_value)
{
if((settings.flags.rotary_fix_enable = int_value != 0))
settings.flags.revert_metric_conversion = !!(int_value & 0b10);
else
settings.flags.revert_metric_conversion = Off;
return Status_OK;
}
#endif
static status_code_t set_sleep_enable (setting_id_t id, uint_fast16_t int_value)
{
settings.flags.sleep_enable = int_value != 0;
@@ -1829,6 +1846,11 @@ FLASHMEM static uint32_t get_int (setting_id_t id)
value = settings.flags.m98_prescan_enable;
break;
#if N_AXIS > 3
case Setting_RotaryOptions:
value = settings.flags.rotary_fix_enable | (settings.flags.revert_metric_conversion << 1);
break;
#endif
default:
break;
}
@@ -2449,7 +2471,10 @@ PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_MotorFaultsInvert, Group_Stepper, "Invert motor fault inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, is_setting_available },
{ Setting_ResetActions, Group_General, "Reset actions", NULL, Format_Bitfield, "Clear homed status if position was lost,Clear offsets (except G92),Clear rapids override,Clear feed override", NULL, NULL, Setting_IsExtendedFn, set_reset_actions, get_int, NULL },
{ Setting_StepperEnableDelay, Group_Stepper, "Stepper enable delay", "ms", Format_Int16, "##0", NULL, "500", Setting_IsExtended, &settings.stepper_enable_delay, NULL, NULL },
{ Setting_SubroutineOptions, Group_General, "Subroutine options", NULL, Format_Bitfield, "Prescan for internal M98 subroutines", NULL, NULL, Setting_IsExtendedFn, set_suboptions, get_int, is_setting_available }
{ Setting_SubroutineOptions, Group_General, "Subroutine options", NULL, Format_Bitfield, "Prescan for internal M98 subroutines", NULL, NULL, Setting_IsExtendedFn, set_suboptions, get_int, is_setting_available },
#if N_AXIS > 3
{ Setting_RotaryOptions, Group_General, "Rotary options", NULL, Format_XBitfield, "Fix feedrate,Revert metric conversion", NULL, NULL, Setting_IsExpandedFn, set_rotary_options, get_int, NULL },
#endif
};
PROGMEM static const setting_descr_t setting_descr[] = {
@@ -2658,6 +2683,11 @@ PROGMEM static const setting_descr_t setting_descr[] = {
{ Setting_CoolantOnDelay, "Delay to allow coolant to start. 0 or 0.5 - 20s." },
{ Setting_ResetActions, "Controls actions taken on a soft reset." },
{ Setting_StepperEnableDelay, "Delay from stepper enable to first step output. The driver typically adds ~2ms to this." },
#if N_AXIS > 3
{ Setting_RotaryOptions, "`Fix feedrate` changes feedrate to inverse time mode for combined angular and linear moves.\\n"
"'Revert metric conversion' reverts feedrate conversion from imperial to metric for angular moves."},
#endif
// { Setting_SubroutineOptions, "Enable prescan for internal M98 subroutines." }
/*
{ Setting_MotorWarningsEnable, "Motor warning enable" },
+4 -1
View File
@@ -465,6 +465,7 @@ typedef enum {
// 683 - 689 - reserved for Sienci
Setting_SubroutineOptions = 700,
Setting_RotaryOptions = 701,
Setting_SpindlePWMOptions1 = 709,
@@ -608,7 +609,9 @@ typedef union {
keep_rapids_override_on_reset :1,
keep_feed_override_on_reset :1,
m98_prescan_enable :1,
unassigned :8;
rotary_fix_enable :1,
revert_metric_conversion :1, // For rotary axes inch/min -> mm/min
unassigned :7;
};
} settingflags_t;
+1 -1
View File
@@ -535,7 +535,7 @@ FLASHMEM static void state_await_hold (uint_fast16_t rt_exec)
// Parking requires parking axis homed, the current location not exceeding the
// parking target location, and laser mode disabled.
if (settings.parking.flags.enabled && !sys.override.control.parking_disable && gc_spindle_get(0)->hal->cap.laser) {
if(settings.parking.flags.enabled && !(sys.override.control.parking_disable || gc_spindle_get(0)->hal->cap.laser)) {
// Get current position and store as restore location.
if (!park.flags.active) {