diff --git a/README.md b/README.md
index 8afb5c3..18a09e6 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/changelog.md b/changelog.md
index 007e8af..85ec772 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,6 +1,25 @@
## grblHAL changelog
-Build 20260803
+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.
+
+---
+
+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:
diff --git a/config.h b/config.h
index 428348f..367e312 100644
--- a/config.h
+++ b/config.h
@@ -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.
*/
diff --git a/gcode.c b/gcode.c
index 96c0ecf..6826252 100644
--- a/gcode.c
+++ b/gcode.c
@@ -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));
}
diff --git a/gcode.h b/gcode.h
index eba0799..a7ad5e0 100644
--- a/gcode.h
+++ b/gcode.h
@@ -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;
diff --git a/grbl.h b/grbl.h
index 929b7ec..d268a00 100644
--- a/grbl.h
+++ b/grbl.h
@@ -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"
diff --git a/motion_control.c b/motion_control.c
index 7d8842b..1f91175 100644
--- a/motion_control.c
+++ b/motion_control.c
@@ -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)
{
diff --git a/motion_control.h b/motion_control.h
index da11717..db4930d 100644
--- a/motion_control.h
+++ b/motion_control.h
@@ -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);
diff --git a/ngc_params.c b/ngc_params.c
index f948f73..09080a0 100644
--- a/ngc_params.c
+++ b/ngc_params.c
@@ -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
};
diff --git a/nuts_bolts.h b/nuts_bolts.h
index 2633083..73b8bfa 100644
--- a/nuts_bolts.h
+++ b/nuts_bolts.h
@@ -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
diff --git a/planner.c b/planner.c
index 8f6b650..567dc1a 100644
--- a/planner.c
+++ b/planner.c
@@ -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.
diff --git a/plugins_init.h b/plugins_init.h
index dca1d65..71c92bc 100644
--- a/plugins_init.h
+++ b/plugins_init.h
@@ -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
diff --git a/report.c b/report.c
index 67dc0cb..f64e1ed 100644
--- a/report.c
+++ b/report.c
@@ -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 == ',')
diff --git a/settings.c b/settings.c
index c3bffaf..90ba97d 100644
--- a/settings.c
+++ b/settings.c
@@ -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" },
diff --git a/settings.h b/settings.h
index 106e6f7..b2ab7cf 100644
--- a/settings.h
+++ b/settings.h
@@ -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;
diff --git a/state_machine.c b/state_machine.c
index f697503..4e4cb5a 100644
--- a/state_machine.c
+++ b/state_machine.c
@@ -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) {