diff --git a/alarms.c b/alarms.c index 2202d40..96962f7 100644 --- a/alarms.c +++ b/alarms.c @@ -46,7 +46,8 @@ PROGMEM static const alarm_detail_t alarm_detail[] = { { Alarm_MotorFault, "Motor fault." }, { Alarm_HomingFail, "Homing fail. Bad configuration." }, { Alarm_ModbusException, "Modbus exception. Timeout or message error." }, - { Alarm_ExpanderException, "I/O expander communication failed." } + { Alarm_ExpanderException, "I/O expander communication failed." }, + { Alarm_NVS_Failed, "Non Volatile Storage (EEPROM) failure." } }; static alarm_details_t details = { diff --git a/alarms.h b/alarms.h index 05d35f9..ef36edc 100644 --- a/alarms.h +++ b/alarms.h @@ -24,7 +24,8 @@ #ifndef _ALARMS_H_ #define _ALARMS_H_ -// Alarm executor codes. Valid values (1-255). Zero is reserved. +// Alarm codes. Valid values (1-255). Zero is reserved. +// Code 0 - 9 is equal to legacy Grbl codes, 15 equals to legacy Grbl code 10 typedef enum { Alarm_None = 0, //!< 0 Alarm_HardLimit = 1, //!< 1 @@ -47,8 +48,9 @@ typedef enum { Alarm_HomingFail = 18, //!< 18 Alarm_ModbusException = 19, //!< 19 Alarm_ExpanderException = 20, //!< 20 - Alarm_AlarmMax = Alarm_ExpanderException -} alarm_code_t; + Alarm_NVS_Failed = 21, //!< 21 + Alarm_AlarmMax = Alarm_NVS_Failed +} __attribute__ ((__packed__)) alarm_code_t; typedef struct { alarm_code_t id; diff --git a/changelog.md b/changelog.md index 80cdac5..eb20c9c 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,55 @@ ## grblHAL changelog +Build 20260125 + +Core: + +* Refactored offset handling, for improved readability and in preparation for rotation support. + +* Added experimental support for `G66` \(modal macro call\) and `G67` \(end modal macro call\). + +* Made axis letter to axis/motor assignment for axes ABCUVW freely changeable at compile time. +Axes configurations such as XYZC and XYZAW is now possible. +> [!NOTE] +> Axis letter to motor assignment has to be in ascending order, e.g. XYZWA will not work. +> Max. number of axes is still limited to 8, capped by the board map. + +* Fix for some `G65` arguments being incorrectly validated for normal use \(sign, range\). + +* Added repeat support to `G65` macro call via the optional `L` parameter word. + +* Changed default setting for ABC-axes to rotary. + +* Changed defaults for jerk settings to 10x acceleration settings. + +* Disabled jerk for jog, probe and spindle synchronized motion. + +* Added `_active_probe` system parameter, returns -1 if no probe inputs available. + +* Minor bug fix, `G5.1` and `G33.1` motion commands were not coverted to the correct string equivalent in `$G` output. + +Drivers: + +* All: updated for new axis letter assigment scheme. +For boards with EEPROM/FRAM an alarm will now be raised if the EEPROM/FRAM cannot be accessed. + +* RP2040: fix for LED strips not working. Ref. issue [#167](https://github.com/grblHAL/RP2040/issues/167). +Fix for second serial port not working on the RP23U5XBB board. Ref. issue [#160](https://github.com/grblHAL/RP2040/issues/160). + +Plugins: + +* Some: updated for new axis letter assigment scheme and other core changes. + +* Networking: ftpd - changed CWD \(Current Working Directory\) handling to be per connection. Ref. PR [#17](https://github.com/grblHAL/Plugin_networking/pull/17). +httpd - added CORS support and some new content types. Ref. PR [#19](https://github.com/grblHAL/Plugin_networking/pull/19). +Some minor bugfixes and general improvements. + +* 3rd party: added M800 plugin to core list. Ref. issue [#30](https://github.com/grblHAL/plugins/issues/30). + +* Misc: removed LED strip configuration plugin, settings `$536` and `$537` are now handled by the core. + +--- + Build 20260107 Core: diff --git a/config.h b/config.h index a675d29..aadfb69 100644 --- a/config.h +++ b/config.h @@ -65,6 +65,13 @@ If more than 3 axes are configured a compliant driver and board map file is need #define N_SYS_SPINDLE 1 #endif +/*! \def PLANNER_ADD_MOTION_MODE +\brief Enables passing the motion mode used to the planner. +*/ +#if !defined PLANNER_ADD_MOTION_MODE || defined __DOXYGEN__ +#define PLANNER_ADD_MOTION_MODE Off // Default disabled. Set to \ref On or 1 to enable. +#endif + /*! \def BUILD_INFO \brief Defines string to be output as part of the `$I` or `$I+` command response. */ @@ -1673,7 +1680,7 @@ greater. /*! @name $47 - Setting_HomingCycle_4 */ ///@{ -#if (defined A_AXIS && !defined DEFAULT_HOMING_CYCLE_3) || defined __DOXYGEN__ +#if (N_AXIS > 3 && !defined DEFAULT_HOMING_CYCLE_3) || defined __DOXYGEN__ #define DEFAULT_HOMING_CYCLE_3 0 // OPTIONAL: Uncomment and add axes mask to enable #endif ///@} @@ -1682,7 +1689,7 @@ greater. \ref axismask */ ///@{ -#if (defined B_AXIS && !defined DEFAULT_HOMING_CYCLE_4) || defined __DOXYGEN__ +#if (N_AXIS > 4 && !defined DEFAULT_HOMING_CYCLE_4) || defined __DOXYGEN__ #define DEFAULT_HOMING_CYCLE_4 0 // OPTIONAL: Uncomment and add axes mask to enable #endif ///@} @@ -1690,7 +1697,7 @@ greater. /*! @name $49 - Setting_HomingCycle_6 */ ///@{ -#if (defined C_AXIS && !defined DEFAULT_HOMING_CYCLE_5) || defined __DOXYGEN__ +#if (N_AXIS > 5 && !defined DEFAULT_HOMING_CYCLE_5) || defined __DOXYGEN__ #define DEFAULT_HOMING_CYCLE_5 0 // OPTIONAL: Uncomment and add axes mask to enable #endif ///@} @@ -1992,8 +1999,36 @@ Set steps/mm for the axes to the value that represent the desired movement per u For the controller the distance is unitless and and can be in degrees, radians, rotations, ... */ ///@{ + +#define IS_ROTARY_LETTER(c) (c == 'A' || c == 'B' || c == 'C') + #if !defined DEFAULT_AXIS_ROTATIONAL_MASK || defined __DOXYGEN__ -#define DEFAULT_AXIS_ROTATIONAL_MASK 0 +#if N_AXIS > 3 && IS_ROTARY_LETTER(AXIS3_LETTER) +#define RA3 (1<<3) +#else +#define RA3 0 +#endif +#if N_AXIS > 4 && IS_ROTARY_LETTER(AXIS4_LETTER) +#define RA4 (1<<4) +#else +#define RA4 0 +#endif +#if N_AXIS > 5 && IS_ROTARY_LETTER(AXIS5_LETTER) +#define RA5 (1<<5) +#else +#define RA5 0 +#endif +#if N_AXIS > 6 && IS_ROTARY_LETTER(AXIS6_LETTER) +#define RA6 (1<<6) +#else +#define RA6 0 +#endif +#if N_AXIS > 7 && IS_ROTARY_LETTER(AXIS7_LETTER) +#define RA7 (1<<7) +#else +#define RA7 0 +#endif +#define DEFAULT_AXIS_ROTATIONAL_MASK (RA3|RA4|RA5|RA6|RA7) #endif ///@} @@ -2117,20 +2152,19 @@ Default baud rate for ModBus RTU stream. Default stream format settings for ModBus RTU stream. */ ///@{ -#if !defined DEFAULT_MODBUS_STREAM_PARITY || defined __DOXYGEN__ -#define DEFAULT_MODBUS_STREAM_PARITY 0 // 0 = None, 1 = Even, 2 = Odd +#if !defined DEFAULT_MODBUS_STREAM_DATA_BITS || defined __DOXYGEN__ +#define DEFAULT_MODBUS_STREAM_DATA_BITS 0 // 0 = 8, 1 = 7 #endif ///@} - -/*! @name $681 - Setting_ModBus_StreamFormat -Default stream format settings for ModBus RTU stream. -*/ ///@{ +#if !defined DEFAULT_MODBUS_STREAM_STOP_BITS || defined __DOXYGEN__ +#define DEFAULT_MODBUS_STREAM_STOP_BITS 0 // 0 = 1, 1 = 1.5, 2 = 2, 3 = 0.5 +#endif +///@}///@{ #if !defined DEFAULT_MODBUS_STREAM_PARITY || defined __DOXYGEN__ #define DEFAULT_MODBUS_STREAM_PARITY 0 // 0 = None, 1 = Even, 2 = Odd #endif ///@} - /*! @name $650 - Setting_FSOptions Filing systems options. */ @@ -2192,6 +2226,9 @@ Adds directory entries in $F and $F+ output to allow hierarchical navigation of #if (defined V_AXIS && !defined DEFAULT_V_STEPS_PER_MM) || defined __DOXYGEN__ #define DEFAULT_V_STEPS_PER_MM 250.0f #endif +#if (defined W_AXIS && !defined DEFAULT_W_STEPS_PER_MM) || defined __DOXYGEN__ +#define DEFAULT_W_STEPS_PER_MM 250.0f +#endif ///@} /*! @name $11x - Setting_AxisMaxRate @@ -2222,6 +2259,9 @@ Adds directory entries in $F and $F+ output to allow hierarchical navigation of #if (defined V_AXIS && !defined DEFAULT_V_MAX_RATE) || defined __DOXYGEN__ #define DEFAULT_V_MAX_RATE 500.0f // mm/min #endif +#if (defined W_AXIS && !defined DEFAULT_W_MAX_RATE) || defined __DOXYGEN__ +#define DEFAULT_W_MAX_RATE 500.0f // mm/min +#endif ///@} /*! @name 12x - Setting_AxisAcceleration @@ -2251,6 +2291,9 @@ Adds directory entries in $F and $F+ output to allow hierarchical navigation of #if (defined V_AXIS && !defined DEFAULT_V_ACCELERATION) || defined __DOXYGEN__ #define DEFAULT_V_ACCELERATION 10.0f // mm/sec^2 #endif +#if (defined W_AXIS && !defined DEFAULT_W_ACCELERATION) || defined __DOXYGEN__ +#define DEFAULT_W_ACCELERATION 10.0f // mm/sec^2 +#endif ///@} /*! @name 22x - Setting_AxisJerk @@ -2280,6 +2323,9 @@ Adds directory entries in $F and $F+ output to allow hierarchical navigation of #if (defined V_AXIS && !defined DEFAULT_V_JERK) || defined __DOXYGEN__ #define DEFAULT_V_JERK (DEFAULT_V_ACCELERATION * 10.0f) // mm/sec^3 #endif +#if (defined W_AXIS && !defined DEFAULT_W_JERK) || defined __DOXYGEN__ +#define DEFAULT_W_JERK (DEFAULT_W_ACCELERATION * 10.0f) // mm/sec^3 +#endif ///@} /*! @name 13x - Setting_AxisMaxTravel @@ -2310,6 +2356,9 @@ __NOTE:__ Must be a positive values. #if (defined V_AXIS && !defined DEFAULT_V_MAX_TRAVEL) || defined __DOXYGEN__ #define DEFAULT_V_MAX_TRAVEL 200.0f // mm #endif +#if (defined W_AXIS && !defined DEFAULT_W_MAX_TRAVEL) || defined __DOXYGEN__ +#define DEFAULT_W_MAX_TRAVEL 200.0f // mm +#endif ///@} /*! @name 14x - Setting_AxisStepperCurrent @@ -2340,6 +2389,9 @@ __NOTE:__ Must be a positive values. #if (defined V_AXIS && !defined DEFAULT_V_CURRENT) || defined __DOXYGEN__ #define DEFAULT_V_CURRENT 500.0f // mA RMS #endif +#if (defined W_AXIS && !defined DEFAULT_W_CURRENT) || defined __DOXYGEN__ +#define DEFAULT_W_CURRENT 500.0f // mA RMS +#endif ///@} // Sanity checks @@ -2389,7 +2441,7 @@ __NOTE:__ Must be a positive values. #error "Cannot enable laser and lathe mode at the same time!" #endif -#if LATHE_UVW_OPTION && (N_AXIS > 6 || AXIS_REMAP_ABC2UVW) +#if LATHE_UVW_OPTION && AXIS_REMAP_ABC2UVW #warning "Cannot enable lathe UVW option when N_AXIS > 6 or ABC words are remapped!" #undef LATHE_UVW_OPTION #define LATHE_UVW_OPTION Off diff --git a/core_handlers.h b/core_handlers.h index d923918..a23c1f9 100644 --- a/core_handlers.h +++ b/core_handlers.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2020-2025 Terje Io + Copyright (c) 2020-2026 Terje Io grblHAL is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +31,7 @@ #include "errors.h" #include "settings.h" #include "report.h" +#include "ioports.h" #include "planner.h" #include "machine_limits.h" #include "vfs.h" @@ -44,13 +45,13 @@ typedef enum { OverrideChanged_FanState = 0 } override_changed_t; -/* TODO: add to grbl pointers so that a different formatting (xml, json etc) of reports may be implemented by a plugin? +/* TODO: add to grblHAL pointers so that a different formatting (xml, json etc) of reports may be implemented by a plugin? typedef struct { void (*report_echo_line_received)(char *line); - void (*report_realtime_status)(stream_write_ptr stream_write); + void (*report_realtime_status)(stream_write_ptr stream_write, ); void (*report_probe_parameters)(void); void (*report_ngc_parameters)(void); - void (*report_gcode_modes)(void); + void (*report_gcode_modes)(stream_write_ptr stream_write); void (*report_startup_line)(uint8_t n, char *line); void (*report_execute_startup_message)(char *line, status_code_t status_code); } grbl_report_t; @@ -89,8 +90,9 @@ typedef void (*on_state_change_ptr)(sys_state_t state); typedef void (*on_override_changed_ptr)(override_changed_t override); typedef void (*on_spindle_programmed_ptr)(spindle_ptrs_t *spindle, spindle_state_t state, float rpm, spindle_rpm_mode_t mode); typedef void (*on_spindle_at_speed_ptr)(spindle_ptrs_t *spindle, spindle_state_t state); +typedef void (*on_port_out_ptr)(uint8_t port, io_port_type_t type, float value); typedef void (*on_wco_changed_ptr)(void); -typedef void (*on_wco_saved_ptr)(coord_system_id_t id, coord_data_t *data); +typedef void (*on_wco_saved_ptr)(coord_system_id_t id, coord_system_data_t *data); typedef void (*on_program_completed_ptr)(program_flow_t program_flow, bool check_mode); typedef void (*on_execute_realtime_ptr)(sys_state_t state); typedef void (*on_unknown_accessory_override_ptr)(uint8_t cmd); @@ -132,7 +134,7 @@ typedef status_code_t (*on_file_end_ptr)(vfs_file_t *handle, status_code_t statu typedef status_code_t (*on_unknown_sys_command_ptr)(sys_state_t state, char *line); // return Status_Unhandled. typedef status_code_t (*on_user_command_ptr)(char *line); typedef sys_commands_t *(*on_get_commands_ptr)(void); -typedef status_code_t (*on_macro_execute_ptr)(macro_id_t macro); // macro implementations _must_ claim hal.stream.read to stream macros! +typedef status_code_t (*on_macro_execute_ptr)(macro_id_t macro, parameter_words_t args, uint32_t repeats); // macro implementations _must_ claim hal.stream.read to stream macros! typedef void (*on_macro_return_ptr)(void); typedef void (*on_file_demarcate_ptr)(bool start); @@ -225,6 +227,7 @@ typedef struct { on_report_handlers_init_ptr on_report_handlers_init; on_spindle_programmed_ptr on_spindle_programmed; on_spindle_at_speed_ptr on_spindle_at_speed; + on_port_out_ptr on_port_out; //!< Might be called from interrupt context, only for unclaimed ports. on_wco_changed_ptr on_wco_changed; on_wco_saved_ptr on_wco_saved; on_program_completed_ptr on_program_completed; @@ -247,7 +250,6 @@ typedef struct { on_control_signals_changed_ptr on_control_signals_changed; //!< Called from interrupt context. NOTE: this is only for cycle start and some of the optional signals. on_unknown_realtime_cmd_ptr on_unknown_realtime_cmd; //!< Called from interrupt context. on_unknown_sys_command_ptr on_unknown_sys_command; //!< Return Status_Unhandled if not handled. - on_get_commands_ptr on_get_commands; //!< Deprecated, use system_register_commands() to register new commands. on_user_command_ptr on_user_command; on_stream_changed_ptr on_stream_changed; on_mpg_registered_ptr on_mpg_registered; diff --git a/crossbar.c b/crossbar.c index f5d2ac1..c790e39 100644 --- a/crossbar.c +++ b/crossbar.c @@ -37,20 +37,24 @@ axes_signals_t xbar_fn_to_axismask (pin_function_t fn) mask.x = mask.y = On; break; -#if N_AXIS > 3 +#if defined(A_AXIS) || defined(B_AXIS) case Output_StepperEnableAB: +#ifdef A_AXIS mask.a = On; -#if N_AXIS > 4 +#endif +#ifdef B_AXIS mask.b = On; #endif break; #endif + case Input_LimitX: case Input_LimitX_Max: case Input_LimitX_2: case Input_HomeX: case Input_MotorFaultX: case Input_MotorFaultX_2: + case Output_StepperEnableX: mask.x = On; break; @@ -60,6 +64,7 @@ axes_signals_t xbar_fn_to_axismask (pin_function_t fn) case Input_HomeY: case Input_MotorFaultY: case Input_MotorFaultY_2: + case Output_StepperEnableY: mask.y = On; break; @@ -69,53 +74,65 @@ axes_signals_t xbar_fn_to_axismask (pin_function_t fn) case Input_HomeZ: case Input_MotorFaultZ: case Input_MotorFaultZ_2: + case Output_StepperEnableZ: mask.z = On; break; -#if N_AXIS > 3 +#ifdef A_AXIS case Input_LimitA: case Input_LimitA_Max: case Input_HomeA: case Input_MotorFaultA: + case Output_StepperEnableA: mask.a = On; break; #endif -#if N_AXIS > 4 +#ifdef B_AXIS case Input_LimitB: case Input_LimitB_Max: case Input_HomeB: case Input_MotorFaultB: + case Output_StepperEnableB: mask.b = On; break; #endif -#if N_AXIS > 5 +#ifdef C_AXIS case Input_LimitC: case Input_LimitC_Max: case Input_HomeC: case Input_MotorFaultC: + case Output_StepperEnableC: mask.c = On; break; #endif -#if N_AXIS > 6 +#ifdef U_AXIS case Input_LimitU: case Input_LimitU_Max: case Input_HomeU: case Input_MotorFaultU: + case Output_StepperEnableU: mask.u = On; break; #endif -#if N_AXIS == 8 +#ifdef V_AXIS case Input_LimitV: case Input_LimitV_Max: case Input_HomeV: case Input_MotorFaultV: + case Output_StepperEnableV: mask.v = On; break; #endif - +#ifdef W_AXIS + case Input_LimitW: + case Input_LimitW_Max: + case Input_HomeW: + case Input_MotorFaultW: + case Output_StepperEnableW: + mask.w = On; + break; +#endif default: - if(fn >= Output_StepperEnableX && fn <= Output_StepperEnableV) - mask.bits = (1 << (fn - Output_StepperEnableX)); break; } diff --git a/crossbar.h b/crossbar.h index 83937ef..e7f1d2b 100644 --- a/crossbar.h +++ b/crossbar.h @@ -50,6 +50,7 @@ typedef enum { Input_MotorFaultC, Input_MotorFaultU, Input_MotorFaultV, + Input_MotorFaultW, Input_MotorFaultX_2, Input_MotorFaultY_2, Input_MotorFaultZ_2, @@ -91,6 +92,9 @@ typedef enum { Input_LimitV, Input_LimitV_Max, Input_HomeV, + Input_LimitW, + Input_LimitW_Max, + Input_HomeW, Input_SpindleIndex, Input_SpindlePulse, Input_Aux0, @@ -143,6 +147,7 @@ typedef enum { Output_StepC, Output_StepU, Output_StepV, + Output_StepW, Output_DirX, Output_DirX2, Output_DirX_2 = Output_DirX2, // deprecated @@ -157,6 +162,7 @@ typedef enum { Output_DirC, Output_DirU, Output_DirV, + Output_DirW, Output_MotorChipSelect, Output_MotorChipSelectX, Output_MotorChipSelectY, @@ -180,6 +186,7 @@ typedef enum { Output_StepperEnableC, Output_StepperEnableU, Output_StepperEnableV, + Output_StepperEnableW, Output_StepperEnableXY, Output_StepperEnableAB, Output_SpindleOn, @@ -419,6 +426,15 @@ PROGMEM static const pin_name_t pin_names[] = { { .function = Input_LimitV_Max, .name = "V limit max" }, { .function = Input_HomeV, .name = "V home" }, { .function = Input_MotorFaultV, .name = "V motor fault" }, +#endif +#ifdef W_AXIS + { .function = Output_StepW, .name = "W step" }, + { .function = Output_DirW, .name = "W dir" }, + { .function = Output_StepperEnableW, .name = "W enable" }, + { .function = Input_LimitW, .name = "W limit min" }, + { .function = Input_LimitW_Max, .name = "W limit max" }, + { .function = Input_HomeW, .name = "W home" }, + { .function = Input_MotorFaultW, .name = "W motor fault" }, #endif { .function = Output_MotorChipSelect, .name = "Motor CS" }, { .function = Output_MotorChipSelectX, .name = "Motor CSX" }, diff --git a/errors.h b/errors.h index 142838f..5dfe777 100644 --- a/errors.h +++ b/errors.h @@ -27,6 +27,7 @@ #include // Define grblHAL status codes. Valid values (0-255) +// Code 0 - 38 is equal to legacy Grbl codes typedef enum { Status_OK = 0, Status_ExpectedCommandLetter = 1, diff --git a/expanders_init.h b/expanders_init.h index 848ba27..f4dec2b 100644 --- a/expanders_init.h +++ b/expanders_init.h @@ -5,7 +5,7 @@ io_expanders_init() should be called at the end of the drivers driver_init() implementation, just before the driver claims ports. - These are NOT referenced in the core grbl code + These are NOT referenced in the core grblHAL code Part of grblHAL diff --git a/gcode.c b/gcode.c index 281eafc..96f366b 100644 --- a/gcode.c +++ b/gcode.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2025 Terje Io + Copyright (c) 2017-2026 Terje Io Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -390,14 +390,10 @@ void gc_init (bool stop) } } else { - coord_data_t tlo; coord_system_id_t coord_system_id = gc_state.modal.coord_system.id; tool_offset_mode_t tool_offset_mode = gc_state.modal.tool_offset_mode; - memcpy(&tlo, gc_state.modal.tool_length_offset, sizeof(coord_data_t)); memset(&gc_state, 0, offsetof(parser_state_t, g92_coord_offset)); - memcpy(gc_state.modal.tool_length_offset, &tlo, sizeof(coord_data_t)); - gc_state.tool_pending = gc_state.tool->tool_id; if(hal.tool.select) hal.tool.select(gc_state.tool, false); @@ -966,6 +962,16 @@ status_code_t gc_execute_block (char *block) #endif // NGC_EXPRESSIONS_ENABLE +#ifdef ROTATION_ENABLE + + static const axes_signals_t rotate_axes[] = { + { .x = On, .y = On }, + { .x = On, .z = On }, + { .y = On, .z = On } + }; + +#endif + char *message = NULL; status_code_t status = Status_OK; struct { @@ -3157,6 +3163,11 @@ status_code_t gc_execute_block (char *block) } while(idx); } +#ifdef ROTATION_ENABLE + if(gc_block.modal.g5x_offset.data.rotation != 0.0f) + rotate((coord_data_t *)gc_block.values.ijk, plane, gc_block.modal.g5x_offset.data.rotation); +#endif + // Arc radius from center to target x -= gc_block.values.ijk[plane.axis_0]; // Delta x between circle center and target y -= gc_block.values.ijk[plane.axis_1]; // Delta y between circle center and target diff --git a/gcode.h b/gcode.h index 9003cad..ce5fd27 100644 --- a/gcode.h +++ b/gcode.h @@ -57,6 +57,8 @@ typedef enum { NonModal_SetHome_1 = 40, //!< 40 - G30.1 NonModal_AbsoluteOverride = 53, //!< 53 - G53 NonModal_MacroCall = 65, //!< 65 - G65 + Modal_MacroCall = 66, //!< 66 - G66 + Modal_MacroEnd = 67, //!< 67 - G67 NonModal_SetCoordinateOffset = 92, //!< 92 - G92 NonModal_ResetCoordinateOffset = 102, //!< 102 - G92.1 NonModal_ClearCoordinateOffset = 112, //!< 112 - G92.2 @@ -92,13 +94,13 @@ typedef enum { MotionMode_RigidTapping = 331, //!< 331 - G33.1 MotionMode_DrillChipBreak = 73, //!< 73 - G73 MotionMode_Threading = 76, //!< 76 - G76 - MotionMode_CannedCycle81 = 81, //!< 81 - G81 - MotionMode_CannedCycle82 = 82, //!< 82 - G82 - MotionMode_CannedCycle83 = 83, //!< 83 - G83 - MotionMode_CannedCycle84 = 84, //!< 83 - G83 - MotionMode_CannedCycle85 = 85, //!< 85 - G85 - MotionMode_CannedCycle86 = 86, //!< 86 - G86 - MotionMode_CannedCycle89 = 89, //!< 89 - G89 + MotionMode_CannedCycle81 = 81, //!< 81 - G81, drill + MotionMode_CannedCycle82 = 82, //!< 82 - G82, drill with dwell + MotionMode_CannedCycle83 = 83, //!< 83 - G83, peck drill + MotionMode_CannedCycle84 = 84, //!< 83 - G84, right hand tapping - experimental + MotionMode_CannedCycle85 = 85, //!< 85 - G85, not implemented + MotionMode_CannedCycle86 = 86, //!< 86 - G86, not implemented + MotionMode_CannedCycle89 = 89, //!< 89 - G89, not implemented MotionMode_ProbeToward = 140, //!< 140 - G38.2 MotionMode_ProbeTowardNoError = 141, //!< 141 - G38.3 MotionMode_ProbeAway = 142, //!< 142 - G38.4 @@ -365,67 +367,56 @@ typedef union { //! Coordinate data including id. typedef struct { - float xyz[N_AXIS]; coord_system_id_t id; + coord_system_data_t data; } coord_system_t; -//! Axis index to plane assignment. -typedef union { - uint8_t axis[3]; - struct { - uint8_t axis_0; - uint8_t axis_1; - uint8_t axis_linear; - }; -} plane_t; - /*! \brief G- and M-code parameter values After the parameters in a block is parsed into the parser blocks (parser_block_t) \a values its corresponding \a words (#parameter_words_t) union holds which parameters were found. -__NOTE:__ Do not use single-meaning words in user defined M-codes. +__NOTE:__ Avoid using single-meaning words in user defined M-codes. */ typedef struct { - float d; //!< Max spindle RPM in Constant Surface Speed Mode (G96) - float e; //!< Thread taper length (G76), M67 output number - float f; //!< Feed rate - single-meaning word - float ijk[3]; //!< I,J,K Axis arc offsets - float k; //!< G33 distance per revolution - float m; //!< G65 argument. - float p; //!< G10, 664 or dwell parameters - float q; //!< User defined M-code parameter, M67 output value, G64 naive CAM tolerance, G83 delta increment - float r; //!< Arc radius or retract position - float s; //!< Spindle speed - single-meaning word + float d; //!< Max spindle RPM in Constant Surface Speed Mode (G96) + float e; //!< Thread taper length (G76), M67 output number + float f; //!< Feed rate - single-meaning word + float h; //!< Tool number or number of G76 thread spring passes + float ijk[3]; //!< I,J,K Axis arc offsets + float k; //!< G33 distance per revolution + float m; //!< G65 argument. + float p; //!< G10, 664 or dwell parameters + float q; //!< User defined M-code parameter, M67 output value, G64 naive CAM tolerance, G83 delta increment + float r; //!< Arc radius or retract position + float s; //!< Spindle speed - single-meaning word + float t; //!< Tool selection - single-meaning word // #ifndef A_AXIS - float a; + float a; //!< G65 argument. #endif #ifndef B_AXIS - float b; + float b; //!< G65 argument. #endif #ifndef C_AXIS - float c; + float c; //!< G65 argument. #endif -#if !defined(U_AXIS) && !AXIS_REMAP_ABC2UVW - float u; +#ifndef U_AXIS + float u; //!< G65 argument. #endif -#if !defined(V_AXIS) && !AXIS_REMAP_ABC2UVW - float v; +#ifndef V_AXIS + float v; //!< G65 argument. #endif -#if !AXIS_REMAP_ABC2UVW - float w; +#ifndef W_AXIS + float w; //!< G65 argument. #endif - float xyz[N_AXIS]; //!< X,Y,Z (and A,B,C,U,V when enabled) translational axes + float xyz[N_AXIS]; //!< X,Y,Z (and A,B,C,U,V when enabled) translational axes #if LATHE_UVW_OPTION - float uvw[3]; //!< U,V,W lathe mode incremental mode motion + float uvw[3]; //!< U,V,W lathe mode incremental mode motion #endif - coord_system_t coord_data; //!< Coordinate data - int32_t $; //!< Spindle id - single-meaning word - int32_t n; //!< Line number - single-meaning word - uint32_t o; //!< Subroutine identifier - single-meaning word - uint32_t h; //!< Tool number or number of G76 thread spring passes - tool_id_t t; //!< Tool selection - single-meaning word - uint8_t l; //!< G10 or canned cycles parameters + int32_t $; //!< Spindle id - single-meaning word + int32_t n; //!< Line number - single-meaning word + uint32_t o; //!< Subroutine identifier - single-meaning word + uint32_t l; //!< G10, G65, G66 or canned cycles parameters } gc_values_t; //! Parameter words found by parser - do NOT change order! @@ -434,9 +425,9 @@ typedef union { uint32_t value; //!< Synonymous with \a mask. struct { uint32_t $ :1, //!< Spindle id. - a :1, //!< A-axis. - b :1, //!< B-axis. - c :1, //!< C-axis. + a :1, //!< A-axis or G65 argument. + b :1, //!< B-axis or G65 argument. + c :1, //!< C-axis or G65 argument. i :1, //!< X-axis offset for arcs. j :1, //!< Y-axis offset for arcs. k :1, //!< Z-axis offset for arcs. @@ -454,28 +445,15 @@ typedef union { r :1, //!< Arc radius, canned cycle retract level. s :1, //!< Spindle speed. t :1, //!< Tool number. - u :1, //!< U-axis. - v :1, //!< V-axis. - w :1, //!< W-axis. + u :1, //!< U-axis or G65 argument. + v :1, //!< V-axis or G65 argument. + w :1, //!< W-axis or G65 argument. x :1, //!< X-axis. y :1, //!< Y-axis. z :1; //!< Z-axis. }; } parameter_words_t; -typedef enum { - ValueType_NA = 0, - ValueType_UInt8, - ValueType_UInt32, - ValueType_Int32, - ValueType_Float -} gc_value_type_t; - -typedef struct { - const void *value; - const gc_value_type_t type; -} gc_value_ptr_t; - typedef union { uint8_t value; struct { @@ -511,7 +489,7 @@ typedef struct { plane_select_t plane_select; //!< {G17,G18,G19} //< uint8_t cutter_comp; //!< {G40} NOTE: Don't track. Only default supported. tool_offset_mode_t tool_offset_mode; //!< {G43,G43.1,G49} - coord_system_t coord_system; //!< {G54,G55,G56,G57,G58,G59,G59.1,G59.2,G59.3} + coord_system_t g5x_offset; //!< {G54,G55,G56,G57,G58,G59,G59.1,G59.2,G59.3} #if ENABLE_PATH_BLENDING control_mode_t control; //!< {G61} NOTE: Don't track. Only default supported. #endif @@ -603,40 +581,60 @@ typedef struct { char name[101]; } tool_pocket_t; +typedef struct { + float angle; + point_2d_t offsets; +} rotation_t; + +#if NGC_PARAMETERS_ENABLE + +typedef struct g66_arguments +{ + uint32_t call_level; + gc_values_t values; + parameter_words_t words; + struct g66_arguments *prev; +} g66_arguments_t; + +#endif + /*! \brief Parser state */ typedef struct { gc_modal_t modal; gc_canned_t canned; - spindle_t *spindle; //!< Last referenced spindle - float feed_rate; //!< Millimeters/min - float distance_per_rev; //!< Millimeters/rev - float position[N_AXIS]; //!< Where the interpreter considers the tool to be at this point in the code + spindle_t *spindle; //!< Last referenced spindle + float feed_rate; //!< Millimeters/min + float distance_per_rev; //!< Millimeters/rev + float position[N_AXIS]; //!< Where the interpreter considers the tool to be at this point in the code #if ENABLE_PATH_BLENDING - float path_tolerance; //!< Path blending tolerance - float cam_tolerance; //!< Naive CAM tolerance + float path_tolerance; //!< Path blending tolerance + float cam_tolerance; //!< Naive CAM tolerance #endif - int32_t line_number; //!< Last line number sent - tool_id_t tool_pending; //!< Tool to be selected on next M6 + uint32_t line_number; //!< Last line number sent + tool_id_t tool_pending; //!< Tool to be selected on next M6 #if NGC_EXPRESSIONS_ENABLE - uint32_t g43_pending; //!< Tool offset to be selected on next M6, for macro ATC + uint32_t g43_pending; //!< Tool offset to be selected on next M6, for macro ATC #endif - bool file_run; //!< Tracks % command - bool file_stream; //!< Tracks streaming from file + bool file_run; //!< Tracks % command + bool file_stream; //!< Tracks streaming from file bool is_laser_ppi_mode; bool is_rpm_rate_adjusted; bool tool_change; - bool skip_blocks; //!< true if skipping conditional blocks - status_code_t last_error; //!< last return value from parser - offset_id_t offset_id; //!< id(x) of last G92 coordinate offset (into circular buffer) + bool skip_blocks; //!< true if skipping conditional blocks + status_code_t last_error; //!< last return value from parser + offset_id_t offset_id; //!< id(x) of last G92 coordinate offset (into circular buffer) coord_data_t offset_queue[MAX_OFFSET_ENTRIES]; //!< The following variables are not cleared upon warm restart when COMPATIBILITY_LEVEL <= 1 - bool g92_coord_offset_applied; //!< true when G92 offset applied - float g92_coord_offset[N_AXIS]; //!< Retains the G92 coordinate offset (work coordinates) relative to - //!< machine zero in mm. Persistent and loaded from non-volatile storage - //!< on boot when COMPATIBILITY_LEVEL <= 1 - tool_data_t *tool; //!< Tracks tool number and tool offset + bool g92_offset_applied; //!< true when G92 offset applied + coord_system_data_t g92_offset; //!< Retains the G92 coordinate offset (work coordinates) relative to + //!< machine zero in mm. Persistent and loaded from non-volatile storage + //!< on boot when COMPATIBILITY_LEVEL <= 1 + tool_data_t *tool; //!< Tracks tool number and tool offset +#if NGC_PARAMETERS_ENABLE + g66_arguments_t *g66_args; //!< Linked list with G66 arguments, NULL if G66 is not active. +#endif } parser_state_t; typedef struct { @@ -662,6 +660,7 @@ typedef struct { parameter_words_t words; //!< Bitfield for tracking found parameter values. output_command_t output_command; //!< Details about M62-M68 output command to execute if present in block. uint32_t arc_turns; // + parameter_words_t g65_words; //!< Parameter words to pass to G65 macro. #if NGC_PARAMETERS_ENABLE modal_state_action_t state_action; //!< M70-M73 modal state action #endif @@ -675,8 +674,31 @@ static inline axes_signals_t gc_paramwords_to_axes (parameter_words_t p_words) { #if N_AXIS == 3 return (axes_signals_t){ (uint8_t)(p_words.mask >> 24) }; -#else +#elif N_AXIS == 7 return (axes_signals_t){ (uint8_t)(((p_words.mask >> 24) | ((p_words.mask << 2) & 0b00111000) | ((p_words.mask >> (21 - 6)) & 0b11000000)) & AXES_BITMASK) }; +#else + axes_signals_t axes = (axes_signals_t){ (uint8_t)(p_words.mask >> 24) }; + + #ifdef A_AXIS + axes.a = p_words.a; + #endif + #ifdef B_AXIS + axes.b = p_words.b; + #endif + #ifdef C_AXIS + axes.c = p_words.c; + #endif + #ifdef U_AXIS + axes.u = p_words.u; + #endif + #ifdef V_AXIS + axes.v = p_words.v; + #endif + #ifdef W_AXIS + axes.w = p_words.w; + #endif + + return axes; #endif } @@ -718,6 +740,7 @@ void gc_coolant (coolant_state_t state); void gc_set_tool_offset (tool_offset_mode_t mode, uint_fast8_t idx, int32_t offset); plane_t *gc_get_plane_data (plane_t *plane, plane_select_t select); +axes_signals_t gc_claim_axis_words (parser_block_t *gc_block, axes_signals_t validate); #if NGC_PARAMETERS_ENABLE parameter_words_t gc_get_g65_arguments (void); diff --git a/grbl.h b/grbl.h index 1138928..1d68c7a 100644 --- a/grbl.h +++ b/grbl.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2025 Terje Io + Copyright (c) 2017-2026 Terje Io Copyright (c) 2015-2016 Sungeun K. Jeon for Gnea Research LLC grblHAL is free software: you can redistribute it and/or modify @@ -42,7 +42,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20260107 +#define GRBL_BUILD 20260126 #define GRBL_URL "https://github.com/grblHAL" @@ -94,7 +94,7 @@ // Do not change unless you know what you are doing! // Define realtime command special characters. These characters are 'picked-off' directly from the -// serial read data stream and are not passed to the grbl line execution parser. Select characters +// serial read data stream and are not passed to the grblHAL line execution parser. Select characters // that do not and must not exist in the streamed g-code program. ASCII control characters may be // used, if they are available per user setup. Also, extended ASCII codes (>127), which are never in // g-code programs, maybe selected for interface programs. diff --git a/grbllib.c b/grbllib.c index 0ff1009..cbf994a 100644 --- a/grbllib.c +++ b/grbllib.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2025 Terje Io + Copyright (c) 2017-2026 Terje Io Copyright (c) 2011-2015 Sungeun K. Jeon Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -447,7 +447,7 @@ int grbl_enter (void) fs_options_t fs_options = { .hierarchical_listing = On }; fs_options.lfs_hidden = hal.driver_cap.littlefs; fs_options.sd_mount_on_boot = hal.driver_cap.sd_card; - setting_remove_elements(Setting_FSOptions, fs_options.mask); + setting_remove_elements(Setting_FSOptions, fs_options.mask, true); } if(hal.stream.state.linestate_event && !hal.stream.state.passthru) { @@ -816,3 +816,8 @@ void task_execute_on_startup (void) grbl.on_execute_realtime(state_get()); } } + +void task_raise_alarm (void *data) +{ + system_raise_alarm((alarm_code_t)data); +} diff --git a/grbllib.h b/grbllib.h index e03e52d..380e326 100644 --- a/grbllib.h +++ b/grbllib.h @@ -6,18 +6,18 @@ Copyright (c) 2011-2015 Sungeun K. Jeon Copyright (c) 2009-2011 Simen Svale Skogsrud - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _GRBLLIB_H_ diff --git a/ioports.c b/ioports.c index 9617c05..3e4f60d 100644 --- a/ioports.c +++ b/ioports.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2021-2025 Terje Io + Copyright (c) 2021-2026 Terje Io grblHAL is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -360,7 +360,7 @@ void ioport_assign_function (aux_ctrl_t *aux_ctrl, pin_function_t *function) hal.signals_cap.mask |= aux_ctrl->signal.mask; if(aux_ctrl->function == Input_Probe || xbar_fn_to_signals_mask(aux_ctrl->function).mask) - setting_remove_elements(Settings_IoPort_InvertIn, ports_cfg[Port_DigitalIn].bus.mask); + setting_remove_elements(Settings_IoPort_InvertIn, ports_cfg[Port_DigitalIn].bus.mask, false); } } @@ -375,7 +375,7 @@ void ioport_assign_out_function (aux_ctrl_out_t *aux_ctrl, pin_function_t *funct ports_cfg[Port_DigitalOut].bus.mask &= ~(1UL << output->id); ports_cfg[Port_DigitalOut].count = ports_cfg[Port_DigitalOut].free = -1; - setting_remove_elements(Settings_IoPort_InvertOut, ports_cfg[Port_DigitalOut].bus.mask); + setting_remove_elements(Settings_IoPort_InvertOut, ports_cfg[Port_DigitalOut].bus.mask, false); } } @@ -402,7 +402,7 @@ bool ioport_set_function (xbar_t *pin, pin_function_t function, driver_caps_t ca if(caps.control) hal.signals_cap.mask |= caps.control->mask; if(function == Input_Probe || function == Input_Probe2 || function == Input_Toolsetter || xbar_fn_to_signals_mask(function).mask) - setting_remove_elements(Settings_IoPort_InvertIn, cfg->bus.mask); + setting_remove_elements(Settings_IoPort_InvertIn, cfg->bus.mask, false); break; case Port_DigitalOut: @@ -418,7 +418,7 @@ bool ioport_set_function (xbar_t *pin, pin_function_t function, driver_caps_t ca default: break; } - setting_remove_elements(Settings_IoPort_InvertOut, cfg->bus.mask); + setting_remove_elements(Settings_IoPort_InvertOut, cfg->bus.mask, false); break; default: break; @@ -744,11 +744,15 @@ static bool io_analog_out (uint8_t port, float value) io_ports_list_t *io_port = ports; io_ports_private_t *cfg = get_port_data(Port_Analog, Port_Output); - port = cfg->map[port]; + uint8_t pn = cfg->map[port]; do { - if(io_port->hal.analog_out && is_match(io_port, Port_Analog, Port_Output, port)) - return io_port->hal.analog_out(port - io_port->ports_id->cfg[Port_Output].n_start, value); + if(io_port->hal.analog_out && is_match(io_port, Port_Analog, Port_Output, pn)) { + bool ok = io_port->hal.analog_out(pn - io_port->ports_id->cfg[Port_Output].n_start, value); + if(ok && grbl.on_port_out && !(cfg->claimed.mask & (1 << pn))) + grbl.on_port_out(port, Port_Analog, value); + return ok; + } } while((io_port = io_port->next)); return false; @@ -759,11 +763,13 @@ static void io_digital_out (uint8_t port, bool on) io_ports_list_t *io_port = ports; io_ports_private_t *cfg = get_port_data(Port_Digital, Port_Output); - port = cfg->map[port]; + uint8_t pn = cfg->map[port]; do { - if(io_port->hal.digital_out && is_match(io_port, Port_Digital, Port_Output, port)) { - io_port->hal.digital_out(port - io_port->ports_id->cfg[Port_Output].n_start, on); + if(io_port->hal.digital_out && is_match(io_port, Port_Digital, Port_Output, pn)) { + io_port->hal.digital_out(pn - io_port->ports_id->cfg[Port_Output].n_start, on); + if(grbl.on_port_out && !(cfg->claimed.mask & (1 << pn))) + grbl.on_port_out(port, Port_Digital, (float)on); break; } } while((io_port = io_port->next)); @@ -886,8 +892,10 @@ static uint8_t add_ports (io_ports_detail_t *ports, uint8_t *map, io_port_type_t if(p_data->ports == NULL) p_data->ports = ports; p_data->count = -1; - } else + } else { ports->n_start = 255; + ports->idx_last = 0; + } p_data->n_ports += n_ports; ports->n_ports = n_ports; @@ -1553,7 +1561,7 @@ static void ioports_configure (settings_t *settings) out_config.open_drain = !!(settings->ioport.od_enable_out.mask & (1 << port)); xbar->config(xbar, &out_config, false); } else // TODO: same for inputs? - setting_remove_elements(Settings_IoPort_InvertOut, cfg->bus.mask & ~(1 << port)); + setting_remove_elements(Settings_IoPort_InvertOut, cfg->bus.mask & ~(1 << port), false); } } while(port); diff --git a/kinematics.h b/kinematics.h index 886a8ed..d770512 100644 --- a/kinematics.h +++ b/kinematics.h @@ -5,18 +5,18 @@ Copyright (c) 2019-2023 Terje Io - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _KINEMATICS_H_ diff --git a/kinematics/corexy.h b/kinematics/corexy.h index 7d2b00f..bdd37cd 100644 --- a/kinematics/corexy.h +++ b/kinematics/corexy.h @@ -6,18 +6,18 @@ Copyright (c) 2019 Terje Io Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _COREXY_H_ diff --git a/kinematics/delta.h b/kinematics/delta.h index 47d1c9f..4b696b6 100644 --- a/kinematics/delta.h +++ b/kinematics/delta.h @@ -5,18 +5,18 @@ Copyright (c) 2023 Terje Io - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _delta_H_ diff --git a/kinematics/polar.h b/kinematics/polar.h index 3172992..715e6c0 100644 --- a/kinematics/polar.h +++ b/kinematics/polar.h @@ -5,18 +5,18 @@ Copyright (c) 2023 Terje Io - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _POLAR_H_ diff --git a/kinematics/wall_plotter.h b/kinematics/wall_plotter.h index d7ed23f..5242a70 100644 --- a/kinematics/wall_plotter.h +++ b/kinematics/wall_plotter.h @@ -5,18 +5,18 @@ Copyright (c) 2019 Terje Io - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _WALL_PLOTTER_H_ diff --git a/machine_limits.c b/machine_limits.c index d23b8a0..9058257 100644 --- a/machine_limits.c +++ b/machine_limits.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2025 Terje Io + Copyright (c) 2017-2026 Terje Io Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -438,7 +438,7 @@ static bool homing_cycle (axes_signals_t cycle, axes_signals_t auto_square) if(rt_exec == EXEC_STATUS_REPORT) { system_clear_exec_state_flag(EXEC_STATUS_REPORT); - report_realtime_status(hal.stream.write_all); + report_realtime_status(hal.stream.write_all, system_get_rt_report_flags()); } else { // Homing failure condition: Reset issued during cycle. diff --git a/machine_limits.h b/machine_limits.h index 7d292d6..83296b6 100644 --- a/machine_limits.h +++ b/machine_limits.h @@ -3,22 +3,22 @@ Part of grblHAL - Copyright (c) 2017-2023 Terje Io + Copyright (c) 2017-2025 Terje Io Copyright (c) 2012-2015 Sungeun K. Jeon Copyright (c) 2009-2011 Simen Svale Skogsrud - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _MACHINE_LIMITS_H_ diff --git a/motion_control.c b/motion_control.c index 4bf62ef..6530a1d 100644 --- a/motion_control.c +++ b/motion_control.c @@ -75,7 +75,7 @@ void mc_sync_backlash_position (void) // Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second // unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in // (1 minute)/feed_rate time. -// NOTE: This is the primary gateway to the grbl planner. All line motions, including arc line +// NOTE: This is the primary gateway to the grblHAL planner. All line motions, including arc line // segments, must pass through this routine before being passed to the planner. The separation of // mc_line and plan_buffer_line is done primarily to place non-planner-type functions from being // in the planner and to let backlash compensation or canned cycle integration simple and direct. @@ -1006,7 +1006,7 @@ gc_probe_t mc_probe_cycle (float *target, plan_line_data_t *pl_data, gc_parser_f sys.probe_position[idx] = lroundf(target[idx] * settings.axis[idx].steps_per_mm); } while(idx); - sys.probe_coordsys_id = gc_state.modal.coord_system.id; + sys.probe_coordsys_id = gc_state.modal.g5x_offset.id; // Finish all queued commands and empty planner buffer before starting probe cycle. if (!protocol_buffer_synchronize()) diff --git a/motion_control.h b/motion_control.h index 6cc4456..114f222 100644 --- a/motion_control.h +++ b/motion_control.h @@ -7,18 +7,18 @@ Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _MOTION_CONTROL_H_ diff --git a/motor_pins.h b/motor_pins.h index bd8527f..cfb01ca 100644 --- a/motor_pins.h +++ b/motor_pins.h @@ -23,6 +23,268 @@ #pragma once +#define CAT(a, b) CAT_(a, b) +#define CAT_(a, b) a##b + +#define MOTOR_IO(n, t) CAT(M, CAT(n, t)) + +#define mn_has_limit(a) \ + (a == 3 ? defined(M3_LIMIT_PIN) : \ + (a == 4 ? defined(M4_LIMIT_PIN) : \ + (a == 5 ? defined(M5_LIMIT_PIN) : \ + (a == 6 ? defined(M6_LIMIT_PIN) : \ + (a == 7 ? defined(M7_LIMIT_PIN) : 0))))) + +#define mn_has_home(a) \ + (a == 3 ? defined(M3_HOME_PIN) : \ + (a == 4 ? defined(M4_HOME_PIN) : \ + (a == 5 ? defined(M5_HOME_PIN) : \ + (a == 6 ? defined(M6_HOME_PIN) : \ + (a == 7 ? defined(M7_HOME_PIN) : 0))))) + +#define mn_has_limit_max(a) \ + (a == 3 ? defined(M3_LIMIT_PIN_MAX) : \ + (a == 4 ? defined(M4_LIMIT_PIN_MAX) : \ + (a == 5 ? defined(M5_LIMIT_PIN_MAX) : \ + (a == 6 ? defined(M6_LIMIT_PIN_MAX) : \ + (a == 7 ? defined(M7_LIMIT_PIN_MAX) : 0))))) + +#define mn_has_fault(a) \ + (a == 3 ? defined(M3_MOTOR_FAULT_PIN) : \ + (a == 4 ? defined(M4_MOTOR_FAULT_PIN) : \ + (a == 5 ? defined(M5_MOTOR_FAULT_PIN) : \ + (a == 6 ? defined(M6_MOTOR_FAULT_PIN) : \ + (a == 7 ? defined(M7_MOTOR_FAULT_PIN) : 0))))) + +#define mn_has_enable(a) \ + (a == 3 ? defined(M3_ENABLE_PIN) : \ + (a == 4 ? defined(M4_ENABLE_PIN) : \ + (a == 5 ? defined(M5_ENABLE_PIN) : \ + (a == 6 ? defined(M6_ENABLE_PIN) : \ + (a == 7 ? defined(M7_ENABLE_PIN) : 0))))) + +#define N_MOTORS (3 + defined(M3_AVAILABLE) + defined(M4_AVAILABLE) + defined(M5_AVAILABLE) + defined(M6_AVAILABLE) + defined(M7_AVAILABLE)) + +#if N_AXIS > 3 + #if !defined(M3_STEP_BIT) + #define M3_STEP_BIT (1<>M3_LIMIT_PIN) + #else + #define M3_LIMIT_BIT 0 + #endif + #endif + #if !defined(M3_LIMIT_MAX_BIT) + #ifdef M3_LIMIT_MAX_PIN + #define M3_LIMIT_MAX_BIT (1< 4 + #if !defined(M4_STEP_BIT) + #define M4_STEP_BIT (1<>M4_LIMIT_PIN) + #else + #define M4_LIMIT_BIT 0 + #endif + #endif + #if !defined(M4_LIMIT_MAX_BIT) + #ifdef M4_LIMIT_MAX_PIN + #define M4_LIMIT_MAX_BIT (1< 5 + #if !defined(M5_STEP_BIT) + #define M5_STEP_BIT (1<>M5_LIMIT_PIN) + #else + #define M5_LIMIT_BIT 0 + #endif + #endif + #if !defined(M5_LIMIT_MAX_BIT) + #ifdef M5_LIMIT_MAX_PIN + #define M5_LIMIT_MAX_BIT (1< 6 + #if !defined(M6_STEP_BIT) + #define M6_STEP_BIT (1<>M6_LIMIT_PIN) + #else + #define M6_LIMIT_BIT 0 + #endif + #endif + #if !defined(M6_LIMIT_MAX_BIT) + #ifdef M6_LIMIT_MAX_PIN + #define M6_LIMIT_MAX_BIT (1< 7 + #if !defined(M7_STEP_BIT) + #define M7_STEP_BIT (1<>M7_LIMIT_PIN) + #else + #define M7_LIMIT_BIT 0 + #endif + #endif + #if !defined(M7_LIMIT_MAX_BIT) + #ifdef M7_LIMIT_MAX_PIN + #define M7_LIMIT_MAX_BIT (1< N_ABC_MOTORS @@ -38,773 +300,218 @@ #endif #if Z_GANGED -#define Z_DOUBLED N_ABC_MOTORS + #if N_MOTORS == 8 + #define Z2_MOTOR_IDX 7 + #elif N_MOTORS == 7 + #define Z2_MOTOR_IDX 6 + #elif N_MOTORS == 6 + #define Z2_MOTOR_IDX 5 + #elif N_MOTORS == 5 + #define Z2_MOTOR_IDX 4 + #elif N_MOTORS == 4 + #define Z2_MOTOR_IDX 3 + #endif #elif Y_GANGED -#define Y_DOUBLED N_ABC_MOTORS + #if N_MOTORS == 8 + #define Y2_MOTOR_IDX 7 + #elif N_MOTORS == 7 + #define Y2_MOTOR_IDX 6 + #elif N_MOTORS == 6 + #define Y2_MOTOR_IDX 5 + #elif N_MOTORS == 5 + #define Y2_MOTOR_IDX 4 + #elif N_MOTORS == 4 + #define Y2_MOTOR_IDX 3 + #endif #elif X_GANGED -#define X_DOUBLED N_ABC_MOTORS + #if N_MOTORS == 8 + #define X2_MOTOR_IDX 7 + #elif N_MOTORS == 7 + #define X2_MOTOR_IDX 6 + #elif N_MOTORS == 6 + #define X2_MOTOR_IDX 5 + #elif N_MOTORS == 5 + #define X2_MOTOR_IDX 4 + #elif N_MOTORS == 4 + #define X2_MOTOR_IDX 3 + #endif #endif -#if Y_GANGED && !defined(Y_DOUBLED) -#define Y_DOUBLED (N_ABC_MOTORS - 1) -#elif X_GANGED && !defined(X_DOUBLED) -#define X_DOUBLED (N_ABC_MOTORS - 1) +#if Y_GANGED && !defined(Y2_MOTOR_IDX) + #if N_MOTORS == 8 + #define Y2_MOTOR_IDX 6 + #elif N_MOTORS == 7 + #define Y2_MOTOR_IDX 5 + #elif N_MOTORS == 6 + #define Y2_MOTOR_IDX 4 + #elif N_MOTORS == 5 + #define Y2_MOTOR_IDX 3 + #endif +#elif X_GANGED && !defined(X2_MOTOR_IDX) + #if N_MOTORS == 8 + #define X2_MOTOR_IDX 6 + #elif N_MOTORS == 7 + #define X2_MOTOR_IDX 5 + #elif N_MOTORS == 6 + #define X2_MOTOR_IDX 4 + #elif N_MOTORS == 5 + #define X2_MOTOR_IDX 3 + #endif #endif -#if X_GANGED && !defined(X_DOUBLED) -#define X_DOUBLED (N_ABC_MOTORS - 2) +#if X_GANGED && !defined(X2_MOTOR_IDX) + #if N_MOTORS == 8 + #define X2_MOTOR_IDX 5 + #elif N_MOTORS == 7 + #define X2_MOTOR_IDX 4 + #elif N_MOTORS == 6 + #define X2_MOTOR_IDX 3 + #endif #endif -#if X_DOUBLED == 1 +#ifdef X2_MOTOR_IDX -#ifdef A_AXIS -#error "A-axis motor is used for ganged X motor" -#endif -#define X2_STEP_PORT M3_STEP_PORT -#define X2_STEP_PIN M3_STEP_PIN -#define X2_STEP_BIT (1<= N_MOTORS + #error "No pins are available for A axis motor" #endif -#ifdef M3_LIMIT_PIN - #define A_LIMIT_PORT M3_LIMIT_PORT - #define A_LIMIT_PIN M3_LIMIT_PIN - #define A_LIMIT_BIT (1<= N_MOTORS + #error "No pins are available for B axis motor" #endif -#ifdef M4_LIMIT_PIN - #define B_LIMIT_PORT M4_LIMIT_PORT - #define B_LIMIT_PIN M4_LIMIT_PIN - #define B_LIMIT_BIT (1<= N_MOTORS + #error "No pins are available for C axis motor" #endif -#ifdef M5_LIMIT_PIN - #define C_LIMIT_PORT M5_LIMIT_PORT - #define C_LIMIT_PIN M5_LIMIT_PIN - #define C_LIMIT_BIT (1<= N_MOTORS + #error "No pins are available for U axis motor" #endif -#ifdef M6_LIMIT_PIN - #define U_LIMIT_PORT M6_LIMIT_PORT - #define U_LIMIT_PIN M6_LIMIT_PIN - #define U_LIMIT_BIT (1<= N_MOTORS + #error "No pins are available for V axis motor" #endif -#ifdef M7_LIMIT_PIN - #define V_LIMIT_PORT M7_LIMIT_PORT - #define V_LIMIT_PIN M7_LIMIT_PIN - #define V_LIMIT_BIT (1<= N_MOTORS + #error "No pins are available for W axis motor" +#endif + +#define W_STEP_PORT MOTOR_IO(W_AXIS_IDX, _STEP_PORT) +#define W_STEP_PIN MOTOR_IO(W_AXIS_IDX, _STEP_PIN) +#define W_STEP_BIT (1<= 4 && !defined(A_ENABLE_BIT) -#define A_ENABLE_BIT 0 -#endif -#if N_AXIS >= 5 && !defined(B_ENABLE_BIT) -#define B_ENABLE_BIT 0 -#endif -#if N_AXIS >= 6 && !defined(C_ENABLE_BIT) -#define C_ENABLE_BIT 0 -#endif - #if N_AXIS == 3 #define STEPPERS_ENABLE_MASK (X_ENABLE_BIT|Y_ENABLE_BIT|Z_ENABLE_BIT) #elif N_AXIS == 4 -#define STEPPERS_ENABLE_MASK (X_ENABLE_BIT|Y_ENABLE_BIT|Z_ENABLE_BIT|A_ENABLE_BIT) +#define STEPPERS_ENABLE_MASK (X_ENABLE_BIT|Y_ENABLE_BIT|Z_ENABLE_BIT|M3_ENABLE_BIT) #elif N_AXIS == 5 -#define STEPPERS_ENABLE_MASK (X_ENABLE_BIT|Y_ENABLE_BIT|Z_ENABLE_BIT|A_ENABLE_BIT|B_ENABLE_BIT) +#define STEPPERS_ENABLE_MASK (X_ENABLE_BIT|Y_ENABLE_BIT|Z_ENABLE_BIT|M3_ENABLE_BIT|M4_ENABLE_BIT) #elif N_AXIS == 6 -#define STEPPERS_ENABLE_MASK (X_ENABLE_BIT|Y_ENABLE_BIT|Z_ENABLE_BIT|A_ENABLE_BIT|B_ENABLE_BIT|C_ENABLE_BIT) +#define STEPPERS_ENABLE_MASK (X_ENABLE_BIT|Y_ENABLE_BIT|Z_ENABLE_BIT|M3_ENABLE_BIT|M4_ENABLE_BIT|M5_ENABLE_BIT) #elif N_AXIS == 7 -#define STEPPERS_ENABLE_MASK (X_ENABLE_BIT|Y_ENABLE_BIT|Z_ENABLE_BIT|A_ENABLE_BIT|B_ENABLE_BIT|C_ENABLE_BIT|U_ENABLE_BIT) +#define STEPPERS_ENABLE_MASK (X_ENABLE_BIT|Y_ENABLE_BIT|Z_ENABLE_BIT|M3_ENABLE_BIT|M4_ENABLE_BIT|M5_ENABLE_BIT|M6_ENABLE_BIT) #else -#define STEPPERS_ENABLE_MASK (X_ENABLE_BIT|Y_ENABLE_BIT|Z_ENABLE_BIT|A_ENABLE_BIT|B_ENABLE_BIT|C_ENABLE_BIT|U_ENABLE_BIT|V_ENABLE_BIT) +#define STEPPERS_ENABLE_MASK (X_ENABLE_BIT|Y_ENABLE_BIT|Z_ENABLE_BIT|M3_ENABLE_BIT|M4_ENABLE_BIT|M5_ENABLE_BIT|M6_ENABLE_BIT|M7_ENABLE_BIT) #endif #endif @@ -1364,62 +1148,26 @@ #define HOME_MASK_SUM HOME_MASK_BASE_SUM #define HOME_MIN_CAP AXES_BITMASK #elif N_AXIS == 4 -#define HOME_MASK (HOME_MASK_BASE|A_HOME_BIT) -#define HOME_MASK_SUM (HOME_MASK_BASE_SUM+A_HOME_BIT) +#define HOME_MASK (HOME_MASK_BASE|M3_HOME_BIT) +#define HOME_MASK_SUM (HOME_MASK_BASE_SUM+M3_HOME_BIT) #elif N_AXIS == 5 -#define HOME_MASK (HOME_MASK_BASE|A_HOME_BIT|B_HOME_BIT) -#define HOME_MASK_SUM (HOME_MASK_BASE_SUM+A_HOME_BIT+B_HOME_BIT) +#define HOME_MASK (HOME_MASK_BASE|M3_HOME_BIT|M4_HOME_BIT) +#define HOME_MASK_SUM (HOME_MASK_BASE_SUM+M3_HOME_BIT+M4_HOME_BIT) #elif N_AXIS == 6 -#define HOME_MASK (HOME_MASK_BASE|A_HOME_BIT|B_HOME_BIT|C_HOME_BIT) -#define HOME_MASK_SUM (HOME_MASK_BASE_SUM+A_HOME_BIT+B_HOME_BIT+C_HOME_BIT) +#define HOME_MASK (HOME_MASK_BASE|M3_HOME_BIT|M4_HOME_BIT|M5_HOME_BIT) +#define HOME_MASK_SUM (HOME_MASK_BASE_SUM+M3_HOME_BIT+M4_HOME_BIT+M5_HOME_BIT) #elif N_AXIS == 7 -#define HOME_MASK (HOME_MASK_BASE|A_HOME_BIT|B_HOME_BIT|C_HOME_BIT|U_HOME_BIT) -#define HOME_MASK_SUM (HOME_MASK_BASE_SUM+A_HOME_BIT+B_HOME_BIT+C_HOME_BIT+U_HOME_BIT) +#define HOME_MASK (HOME_MASK_BASE|M3_HOME_BIT|M4_HOME_BIT|M5_HOME_BIT|M6_HOME_BIT) +#define HOME_MASK_SUM (HOME_MASK_BASE_SUM+M3_HOME_BIT+M4_HOME_BIT+M5_HOME_BIT+M6_HOME_BIT) #else -#define HOME_MASK (HOME_MASK_BASE|A_HOME_BIT|B_HOME_BIT|C_HOME_BIT|U_HOME_BIT|V_HOME_BIT) -#define HOME_MASK_SUM (HOME_MASK_BASE_SUM+A_HOME_BIT+B_HOME_BIT+C_HOME_BIT+U_HOME_BIT+V_HOME_BIT) +#define HOME_MASK (HOME_MASK_BASE|M3_HOME_BIT|M4_HOME_BIT|M5_HOME_BIT|M6_HOME_BIT|M7_HOME_BIT) +#define HOME_MASK_SUM (HOME_MASK_BASE_SUM+M3_HOME_BIT+M4_HOME_BIT+M5_HOME_BIT+M6_HOME_BIT+M7_HOME_BIT) #endif #endif // HOME_MASK #ifndef LIMIT_MASK -#if N_AXIS >=4 && !defined(A_LIMIT_BIT) -#ifdef A_LIMIT_PIN -#define A_LIMIT_BIT (1<=5 && !defined(B_LIMIT_BIT) -#ifdef B_LIMIT_PIN -#define B_LIMIT_BIT (1<= 6 && !defined(C_LIMIT_BIT) -#ifdef C_LIMIT_PIN -#define C_LIMIT_BIT (1<= 7 && !defined(U_LIMIT_BIT) -#ifdef U_LIMIT_PIN -#define U_LIMIT_BIT (1<. + along with grblHAL. If not, see . */ #ifndef ADD_MY_PLUGIN diff --git a/ngc_params.c b/ngc_params.c index 5d2ef58..5d0108f 100644 --- a/ngc_params.c +++ b/ngc_params.c @@ -95,6 +95,47 @@ static ngc_string_id_t ref_id = (uint32_t)-1; static ngc_string_param_t *ngc_string_params = NULL; static on_macro_execute_ptr on_macro_execute; +static const uint8_t axis_map[] = { +#ifdef ROTATION_ENABLE + 10, +#else + 255, // R - XY rotation angle around the Z axis. N/A. +#endif + X_AXIS, + Y_AXIS, + Z_AXIS, +#ifdef A_AXIS + A_AXIS, +#else + 255, +#endif +#ifdef B_AXIS + B_AXIS, +#else + 255, +#endif +#ifdef C_AXIS + C_AXIS, +#else + 255, +#endif +#ifdef U_AXIS + U_AXIS, +#else + 255, +#endif +#ifdef V_AXIS + V_AXIS, +#else + 255, +#endif +#ifdef W_AXIS + W_AXIS +#else + 255 +#endif +}; + #if N_AXIS > 3 static float _convert_pos (float value, uint_fast8_t axis) @@ -113,12 +154,16 @@ static inline float _convert_pos (float value, uint_fast8_t axis) static float _absolute_pos (uint_fast8_t axis) { - return _convert_pos(axis < N_AXIS ? sys.position[axis] / settings.axis[axis].steps_per_mm : 0.0f, axis); + axis = axis_map[axis]; + + return _convert_pos(axis <= 9 ? sys.position[axis] / settings.axis[axis].steps_per_mm : 0.0f, axis); } static float _relative_pos (uint_fast8_t axis) { - return _convert_pos(axis < N_AXIS ? sys.position[axis] / settings.axis[axis].steps_per_mm - gc_get_offset(axis, false) : 0.0f, axis); + axis = axis_map[axis]; + + return _convert_pos(axis <= 9 ? sys.position[axis] / settings.axis[axis].steps_per_mm - gc_get_offset(axis, false) : 0.0f, axis); } // numbered parameters @@ -126,12 +171,12 @@ static float _relative_pos (uint_fast8_t axis) static float probe_coord (ngc_param_id_t id) { float value = 0.0f; - uint_fast8_t axis = (id % 10) - 1; - coord_system_t data; + uint_fast8_t axis = axis_map[(id % 10)]; + coord_system_data_t offset; - if(axis < N_AXIS && (sys.probe_coordsys_id == gc_state.modal.coord_system.id || settings_read_coord_data(sys.probe_coordsys_id, &data.xyz))) + if(axis <= 9 && (sys.probe_coordsys_id == gc_state.modal.g5x_offset.id || settings_read_coord_data(sys.probe_coordsys_id, &offset))) value = sys.probe_position[axis] / settings.axis[axis].steps_per_mm - - (sys.probe_coordsys_id == gc_state.modal.coord_system.id ? gc_state.modal.coord_system.xyz[axis] : data.xyz[axis]); + (sys.probe_coordsys_id == gc_state.modal.g5x_offset.id ? gc_state.modal.g5x_offset.data.coord.values[axis] : offset.coord.values[axis]); return _convert_pos(value, axis); } @@ -139,9 +184,9 @@ static float probe_coord (ngc_param_id_t id) static float scaling_factors (ngc_param_id_t id) { float *factors = gc_get_scaling(); - uint_fast8_t axis = id % 10; + uint_fast8_t axis = axis_map[(id % 10)]; - return axis <= N_AXIS ? factors[axis - 1] : 0.0f; + return axis <= 9 ? factors[axis] : 0.0f; } static float probe_result (ngc_param_id_t id) @@ -152,7 +197,7 @@ static float probe_result (ngc_param_id_t id) /* static float home_pos (ngc_param_id_t id) { - uint_fast8_t axis = id % 10; + uint_fast8_t axis = axis_map[(id % 10)]; return axis <= N_AXIS ? sys.home_position[axis - 1] : 0.0f; } @@ -169,19 +214,19 @@ static float tool_number (ngc_param_id_t id) static float tool_offset (ngc_param_id_t id) { - uint_fast8_t axis = id % 10; + uint_fast8_t axis = axis_map[(id % 10)]; - return axis <= N_AXIS ? gc_state.modal.tool_length_offset[axis] : 0.0f; + return axis <= 9 ? gc_state.modal.tool_length_offset[axis] : 0.0f; } static float g28_home (ngc_param_id_t id) { float value = 0.0f; - uint_fast8_t axis = id % 10; - coord_system_t data; + uint_fast8_t axis = axis_map[(id % 10)]; + coord_system_data_t offset; - if(axis <= N_AXIS && settings_read_coord_data(CoordinateSystem_G28, &data.xyz)) - value = data.xyz[axis - 1]; + if(axis <= 9 && settings_read_coord_data(CoordinateSystem_G28, &offset)) + value = offset.coord.values[axis]; return value; } @@ -189,55 +234,61 @@ static float g28_home (ngc_param_id_t id) static float g30_home (ngc_param_id_t id) { float value = 0.0f; - uint_fast8_t axis = id % 10; - coord_system_t data; + uint_fast8_t axis = axis_map[(id % 10)]; + coord_system_data_t offset; -#if COMPATIBILITY_LEVEL > 1 - if(id <= CoordinateSystem_G59) { -#endif - if (axis <= N_AXIS && settings_read_coord_data(CoordinateSystem_G30, &data.xyz)) - value = data.xyz[axis - 1]; -#if COMPATIBILITY_LEVEL > 1 - } -#endif + if(axis <= 9 && settings_read_coord_data(CoordinateSystem_G30, &offset)) + value = offset.coord.values[axis]; return value; } static float coord_system (ngc_param_id_t id) { - return (float)gc_state.modal.coord_system.id + 1; + return (float)gc_state.modal.g5x_offset.id + 1; } static float coord_system_offset (ngc_param_id_t id) { float value = 0.0f; uint_fast8_t axis = id % 10; - coord_system_t data; + coord_system_data_t offset; id = (id - 5220 - axis - (id == 0 ? 10 : 0)) / 20; + axis = axis_map[axis]; - if (axis > 0 && axis <= N_AXIS && settings_read_coord_data((coord_system_id_t)id, &data.xyz)) - value = data.xyz[axis - 1]; +#if COMPATIBILITY_LEVEL > 1 + if(id <= CoordinateSystem_G59) { +#endif +#ifdef ROTATION_ENABLE + if(axis <= 10 && settings_read_coord_data((coord_system_id_t)id, &offset)) + value = axis == 10 ? offset.rotation : offset.coord.values[axis]; +#else + if(axis <= 9 && settings_read_coord_data((coord_system_id_t)id, &offset)) + value = offset.coord.values[axis]; +#endif +#if COMPATIBILITY_LEVEL > 1 + } +#endif return value; } static float g92_offset_applied (ngc_param_id_t id) { - return (float)gc_state.g92_coord_offset_applied; + return (float)gc_state.g92_offset_applied; } static float g92_offset (ngc_param_id_t id) { - uint_fast8_t axis = id % 10; + uint_fast8_t axis = axis_map[(id % 10)]; - return axis <= N_AXIS ? gc_state.g92_coord_offset [axis - 1] : 0.0f; + return axis <= 9 ? gc_state.g92_offset.coord.values[axis] : 0.0f; } static float work_position (ngc_param_id_t id) { - return _relative_pos(id % 10); + return _relative_pos(id % 10 + 1); } static float debug_output (ngc_param_id_t id) @@ -246,28 +297,28 @@ static float debug_output (ngc_param_id_t id) } PROGMEM static const ngc_ro_param_t ngc_ro_params[] = { - { .id_min = 5061, .id_max = 5069, .get = probe_coord }, // LinuxCNC - { .id_min = 5070, .id_max = 5070, .get = probe_result }, // LinuxCNC + { .id_min = 5061, .id_max = 5069, .get = probe_coord }, // LinuxCNC + { .id_min = 5070, .id_max = 5070, .get = probe_result }, // LinuxCNC { .id_min = 5161, .id_max = 5169, .get = g28_home }, { .id_min = 5181, .id_max = 5189, .get = g30_home }, - { .id_min = 5191, .id_max = 5199, .get = scaling_factors }, // Mach3 - { .id_min = 5210, .id_max = 5210, .get = g92_offset_applied }, // LinuxCNC + { .id_min = 5191, .id_max = 5199, .get = scaling_factors }, // Mach3 + { .id_min = 5210, .id_max = 5210, .get = g92_offset_applied }, // LinuxCNC { .id_min = 5211, .id_max = 5219, .get = g92_offset }, { .id_min = 5220, .id_max = 5220, .get = coord_system }, - { .id_min = 5221, .id_max = 5230, .get = coord_system_offset }, - { .id_min = 5241, .id_max = 5250, .get = coord_system_offset }, - { .id_min = 5261, .id_max = 5270, .get = coord_system_offset }, - { .id_min = 5281, .id_max = 5290, .get = coord_system_offset }, - { .id_min = 5301, .id_max = 5310, .get = coord_system_offset }, - { .id_min = 5321, .id_max = 5330, .get = coord_system_offset }, - { .id_min = 5341, .id_max = 5350, .get = coord_system_offset }, - { .id_min = 5361, .id_max = 5370, .get = coord_system_offset }, - { .id_min = 5381, .id_max = 5390, .get = coord_system_offset }, - { .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 = 5420, .id_max = 5428, .get = work_position }, // LinuxCNC - { .id_min = 5599, .id_max = 5599, .get = debug_output } // LinuxCNC + { .id_min = 5221, .id_max = 5230, .get = coord_system_offset }, // G54 + { .id_min = 5241, .id_max = 5250, .get = coord_system_offset }, // G55 + { .id_min = 5261, .id_max = 5270, .get = coord_system_offset }, // G56 + { .id_min = 5281, .id_max = 5290, .get = coord_system_offset }, // G57 + { .id_min = 5301, .id_max = 5310, .get = coord_system_offset }, // G58 + { .id_min = 5321, .id_max = 5330, .get = coord_system_offset }, // G59 + { .id_min = 5341, .id_max = 5350, .get = coord_system_offset }, // G59.1 + { .id_min = 5361, .id_max = 5370, .get = coord_system_offset }, // G59.2 + { .id_min = 5381, .id_max = 5390, .get = coord_system_offset }, // G59.3 + { .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 = 5420, .id_max = 5428, .get = work_position }, // LinuxCNC + { .id_min = 5599, .id_max = 5599, .get = debug_output } // LinuxCNC }; bool ngc_param_get (ngc_param_id_t id, float *value) @@ -402,6 +453,7 @@ PROGMEM static const ngc_named_ro_param_t ngc_named_ro_param[] = { { .name = "_probe_state", .id = NGCParam_probe_state }, { .name = "_probe2_state", .id = NGCParam_probe2_state }, { .name = "_toolsetter_state", .id = NGCParam_toolsetter_state }, + { .name = "_active_probe", .id = NGCParam_active_probe }, { .name = "_homed_state", .id = NGCParam_homed_state }, { .name = "_homed_axes", .id = NGCParam_homed_axes }, { .name = "_tool_table_size", .id = NGCParam_tool_table_size }, @@ -470,10 +522,10 @@ float ngc_named_param_get_by_id (ncg_name_param_id_t id) case NGCParam_coord_system: { - uint_fast16_t id = gc_state.modal.coord_system.id * 10; + uint_fast16_t id = gc_state.modal.g5x_offset.id * 10; if(id > (CoordinateSystem_G59 * 10)) - id = (CoordinateSystem_G59 * 10) + gc_state.modal.coord_system.id - CoordinateSystem_G59; + id = (CoordinateSystem_G59 * 10) + gc_state.modal.g5x_offset.id - CoordinateSystem_G59; value = (float)(540 + id); } @@ -568,7 +620,7 @@ float ngc_named_param_get_by_id (ncg_name_param_id_t id) case NGCParam_v: //no break case NGCParam_w: - value = _relative_pos(id - NGCParam_x); + value = _relative_pos(id - NGCParam_x + 1); break; case NGCParam_abs_x: @@ -588,7 +640,7 @@ float ngc_named_param_get_by_id (ncg_name_param_id_t id) case NGCParam_abs_v: //no break case NGCParam_abs_w: - value = _absolute_pos(id - NGCParam_abs_x); + value = _absolute_pos(id - NGCParam_abs_x + 1); break; case NGCParam_current_tool: @@ -625,6 +677,10 @@ float ngc_named_param_get_by_id (ncg_name_param_id_t id) value = hal.driver_cap.toolsetter && hal.probe.is_triggered ? (float)hal.probe.is_triggered(Probe_Toolsetter) : -1.0f; break; + case NGCParam_active_probe: + value = hal.probe.get_state ? (float)hal.probe.get_state().probe_id : -1.0f; + break; + case NGCParam_homed_state: if(sys.homing.mask || settings.homing.flags.single_axis_commands || settings.homing.flags.manual) { axes_signals_t homing = { sys.homing.mask ? sys.homing.mask : AXES_BITMASK }; @@ -917,7 +973,6 @@ gc_modal_snapshot_t *ngc_modal_state_get (void) return call_level == -1 ? modal_state : call_levels[call_level].modal_state; } - bool ngc_modal_state_restore (void) { return gc_modal_state_restore(call_level == -1 ? modal_state : call_levels[call_level].modal_state); @@ -939,40 +994,40 @@ bool ngc_call_pop (void) if(call_context) { - ngc_rw_param_t *rw_param = rw_params, *rw_param_last = rw_params; + ngc_rw_param_t *rw_param = rw_params, *rw_param_last = rw_params; - while(rw_param) { - if(rw_param->context == call_context) { - ngc_rw_param_t *rw_param_free = rw_param; - rw_param = rw_param->next; - if(rw_param_free == rw_params) - rw_params = rw_param_last = rw_param; - else - rw_param_last->next = rw_param; - free(rw_param_free); - } else { - rw_param_last = rw_param; - rw_param = rw_param->next; + while(rw_param) { + if(rw_param->context == call_context) { + ngc_rw_param_t *rw_param_free = rw_param; + rw_param = rw_param->next; + if(rw_param_free == rw_params) + rw_params = rw_param_last = rw_param; + else + rw_param_last->next = rw_param; + free(rw_param_free); + } else { + rw_param_last = rw_param; + rw_param = rw_param->next; + } } - } - ngc_named_rw_param_t *rw_named_param = rw_global_params, *rw_named_param_last = rw_global_params; + ngc_named_rw_param_t *rw_named_param = rw_global_params, *rw_named_param_last = rw_global_params; - while(rw_named_param) { - if(rw_named_param->context == call_context) { - ngc_named_rw_param_t *rw_named_param_free = rw_named_param; - rw_named_param = rw_named_param->next; - if(rw_named_param_free == rw_global_params) - rw_global_params = rw_named_param_last = rw_named_param; - else - rw_named_param_last->next = rw_named_param; - free(rw_named_param_free); - } else { - rw_named_param_last = rw_named_param; - rw_named_param = rw_named_param->next; + while(rw_named_param) { + if(rw_named_param->context == call_context) { + ngc_named_rw_param_t *rw_named_param_free = rw_named_param; + rw_named_param = rw_named_param->next; + if(rw_named_param_free == rw_global_params) + rw_global_params = rw_named_param_last = rw_named_param; + else + rw_named_param_last->next = rw_named_param; + free(rw_named_param_free); + } else { + rw_named_param_last = rw_named_param; + rw_named_param = rw_named_param->next; + } } } - } if(call_levels[call_level].modal_state) { if(call_levels[call_level].modal_state->modal.auto_restore) @@ -997,12 +1052,11 @@ uint8_t ngc_float_decimals (void) return settings.flags.report_inches ? N_DECIMAL_COORDVALUE_INCH : N_DECIMAL_COORDVALUE_MM; } -static status_code_t macro_set_get_setting (void) +static status_code_t macro_set_get_setting (parameter_words_t args) { float setting_id; status_code_t status = Status_OK; const setting_detail_t *setting; - parameter_words_t args = gc_get_g65_arguments(); if(!args.q) status = Status_GcodeValueWordMissing; @@ -1032,11 +1086,10 @@ static status_code_t macro_set_get_setting (void) return status; } -static status_code_t macro_ngc_parameter_rw (void) +static status_code_t macro_ngc_parameter_rw (parameter_words_t args) { float idx, value; status_code_t status = Status_OK; - parameter_words_t args = gc_get_g65_arguments(); if(!args.i) status = Status_GcodeValueWordMissing; @@ -1060,7 +1113,7 @@ static status_code_t macro_ngc_parameter_rw (void) return status; } -static status_code_t macro_get_machine_state (void) +static status_code_t macro_get_machine_state (parameter_words_t args) { ngc_named_param_set("_value", (float)ffs(state_get())); ngc_named_param_set("_value_returned", 1.0f); @@ -1068,11 +1121,10 @@ static status_code_t macro_get_machine_state (void) return Status_OK; } -static status_code_t macro_select_probe (void) +static status_code_t macro_select_probe (parameter_words_t args) { float probe_id; status_code_t status = Status_OK; - parameter_words_t args = gc_get_g65_arguments(); if(!args.q) status = Status_GcodeValueWordMissing; @@ -1084,11 +1136,10 @@ static status_code_t macro_select_probe (void) return status; } -static status_code_t macro_get_tool_offset (void) +static status_code_t macro_get_tool_offset (parameter_words_t args) { float tool_id, axis_id; status_code_t status = Status_OK; - parameter_words_t args = gc_get_g65_arguments(); if(!(args.q && args.r)) status = Status_GcodeValueWordMissing; @@ -1107,30 +1158,32 @@ static status_code_t macro_get_tool_offset (void) return status; } -static status_code_t onMacroExecute (macro_id_t macro_id) +static status_code_t onMacroExecute (macro_id_t macro_id, parameter_words_t args, uint32_t repeats) { - status_code_t status = Status_Unhandled; + status_code_t status = repeats > 1 && macro_id >= 1 && macro_id <= G65Macro_LastInbuilt + ? Status_GcodeValueOutOfRange + : Status_Unhandled; - switch((g65_inbuilt_t)macro_id) { + if(status == Status_Unhandled) switch((g65_inbuilt_t)macro_id) { case G65Macro_GetSetting: - status = macro_set_get_setting(); + status = macro_set_get_setting(args); break; case G65Macro_GetToolOffset: - status = macro_get_tool_offset(); + status = macro_get_tool_offset(args); break; case G65Macro_ParameterRW: - status = macro_ngc_parameter_rw(); + status = macro_ngc_parameter_rw(args); break; case G65Macro_GetMachineState: - status = macro_get_machine_state(); + status = macro_get_machine_state(args); break; case G65Macro_SelectProbe: - status = macro_select_probe(); + status = macro_select_probe(args); break; case G65Macro_SpindleDelayDisable: @@ -1139,7 +1192,7 @@ static status_code_t onMacroExecute (macro_id_t macro_id) break; } - return status == Status_Unhandled && on_macro_execute ? on_macro_execute(macro_id) : status; + return status == Status_Unhandled && on_macro_execute ? on_macro_execute(macro_id, args, repeats) : status; } void ngc_params_init (void) diff --git a/ngc_params.h b/ngc_params.h index f200e0f..2c5954c 100644 --- a/ngc_params.h +++ b/ngc_params.h @@ -103,6 +103,7 @@ typedef enum { NGCParam_probe_state, NGCParam_probe2_state, NGCParam_toolsetter_state, + NGCParam_active_probe, NGCParam_homed_state, NGCParam_homed_axes, NGCParam_tool_table_size, @@ -116,7 +117,8 @@ typedef enum { G65Macro_ParameterRW = 3, G65Macro_GetMachineState = 4, G65Macro_SelectProbe = 5, - G65Macro_SpindleDelayDisable = 6 + G65Macro_SpindleDelayDisable = 6, + G65Macro_LastInbuilt = G65Macro_SpindleDelayDisable } g65_inbuilt_t; void ngc_params_init (void); diff --git a/nuts_bolts.c b/nuts_bolts.c index 6100d16..3b8581e 100644 --- a/nuts_bolts.c +++ b/nuts_bolts.c @@ -61,36 +61,45 @@ static const float froundvalues[MAX_PRECISION + 1] = const coord_data_t null_vector = {0}; -char const *const axis_letter[N_AXIS] = { - "X", - "Y", - "Z" +static const char axis_letters[] = { + AXIS0_LETTER, '\0', + AXIS1_LETTER, '\0', + AXIS2_LETTER, '\0', #if N_AXIS > 3 - #if !AXIS_REMAP_ABC2UVW - ,"A" - #else - ,"U" - #endif + AXIS3_LETTER, '\0', #endif #if N_AXIS > 4 - #if !AXIS_REMAP_ABC2UVW - ,"B" - #else - ,"V" - #endif + AXIS4_LETTER, '\0', #endif #if N_AXIS > 5 - #if !AXIS_REMAP_ABC2UVW - ,"C" - #else - ,"W" - #endif + AXIS5_LETTER, '\0', #endif #if N_AXIS > 6 - ,"U" + AXIS6_LETTER, '\0', #endif #if N_AXIS > 7 - ,"V" + AXIS7_LETTER, '\0', +#endif +}; + +char const *const axis_letter[N_AXIS] = { + &axis_letters[0 << 1], + &axis_letters[1 << 1], + &axis_letters[2 << 1], +#if N_AXIS > 3 + &axis_letters[3 << 1], +#endif +#if N_AXIS > 4 + &axis_letters[4 << 1], +#endif +#if N_AXIS > 5 + &axis_letters[5 << 1], +#endif +#if N_AXIS > 6 + &axis_letters[6 << 1], +#endif +#if N_AXIS > 7 + &axis_letters[7 << 1], #endif }; @@ -352,6 +361,16 @@ float convert_delta_vector_to_unit_vector (float *vector) return magnitude; } +void rotate (coord_data_t *pt, plane_t plane, float angle /*rad*/) +{ + float cos = cosf(angle), sin = sinf(angle), + t0 = pt->values[plane.axis_0] * cos - pt->values[plane.axis_1] * sin, + t1 = pt->values[plane.axis_0] * sin + pt->values[plane.axis_1] * cos; + + pt->values[plane.axis_0] = t0; + pt->values[plane.axis_1] = t1; +} + // parse ISO8601 datetime: YYYY-MM-DDTHH:MM:SSZxxx struct tm *get_datetime (const char *s) { diff --git a/nuts_bolts.h b/nuts_bolts.h index aa62747..39f9991 100644 --- a/nuts_bolts.h +++ b/nuts_bolts.h @@ -53,6 +53,9 @@ #define TAN30_2 0.28867513459481288225f #define ABORTED (sys.abort || sys.cancel) +#define IS_AXIS_LETTER(c) (AXIS3_LETTER == c || AXIS4_LETTER == c || AXIS5_LETTER == c || AXIS6_LETTER == c || AXIS7_LETTER == c) +#define IS_AXIS_LETTER_VALID(c) (c == 'A' || c == 'B' || c == 'C' || c == 'U' || c == 'V' || c == 'W') +//#define AXIS_LETTER_FN_IDX(c) ((c >= 'X' && c <= 'Z') ? ((c - 'X') << 1) : ((c >= 'A' && c <= 'C') ? c - 'A' + 6 : ((c >= 'U' && c <= 'W') ? c - 'U' + 9 : -1))) // Convert character to uppercase #define CAPS(c) ((c >= 'a' && c <= 'z') ? (c & 0x5F) : c) @@ -72,54 +75,174 @@ #define Y_AXIS_BIT bit(Y_AXIS) #define Z_AXIS_BIT bit(Z_AXIS) #if N_AXIS > 3 -#define A_AXIS 3 -#define A_AXIS_BIT bit(A_AXIS) +#define AXIS3_IDX 3 +#define AXIS3_BIT bit(AXIS3_IDX) #endif #if N_AXIS > 4 -#define B_AXIS 4 -#define B_AXIS_BIT bit(B_AXIS) +#define AXIS4_IDX 4 +#define AXIS4_BIT bit(AXIS4_IDX) #endif #if N_AXIS > 5 -#define C_AXIS 5 -#define C_AXIS_BIT bit(C_AXIS) +#define AXIS5_IDX 5 +#define AXIS5_BIT bit(AXIS5_IDX) #endif #if N_AXIS > 6 -#define U_AXIS 6 -#define U_AXIS_BIT bit(U_AXIS) +#define AXIS6_IDX 6 +#define AXIS6_BIT bit(AXIS6_IDX) #endif #if N_AXIS == 8 -#define V_AXIS 7 -#define V_AXIS_BIT bit(V_AXIS) +#define AXIS7_IDX 7 +#define AXIS7_BIT bit(AXIS7_IDX) #endif #if N_AXIS == 3 #define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT) #elif N_AXIS == 4 -#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|A_AXIS_BIT) +#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|AXIS3_BIT) #elif N_AXIS == 5 -#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|A_AXIS_BIT|B_AXIS_BIT) +#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|AXIS3_BIT|AXIS4_BIT) #elif N_AXIS == 6 -#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|A_AXIS_BIT|B_AXIS_BIT|C_AXIS_BIT) +#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|AXIS3_BIT|AXIS4_BIT|AXIS5_BIT) #elif N_AXIS == 7 -#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|A_AXIS_BIT|B_AXIS_BIT|C_AXIS_BIT|U_AXIS_BIT) +#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|AXIS3_BIT|AXIS4_BIT|AXIS5_BIT|AXIS6_BIT) #else -#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|A_AXIS_BIT|B_AXIS_BIT|C_AXIS_BIT|U_AXIS_BIT|V_AXIS_BIT) +#define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|AXIS3_BIT|AXIS4_BIT|AXIS5_BIT|AXIS6_BIT|AXIS7_BIT) #endif -#ifdef V_AXIS +#ifdef AXIS7_IDX #define N_ABC_AXIS 5 -#elif defined(U_AXIS) +#elif defined(AXIS6_IDX) #define N_ABC_AXIS 4 -#elif defined(C_AXIS) +#elif defined(AXIS5_IDX) #define N_ABC_AXIS 3 -#elif defined(B_AXIS) +#elif defined(AXIS4_IDX) #define N_ABC_AXIS 2 -#elif defined(A_AXIS) +#elif defined(AXIS3_IDX) #define N_ABC_AXIS 1 #else #define N_ABC_AXIS 0 #endif +#define AXIS0_LETTER 'X' +#define AXIS1_LETTER 'Y' +#define AXIS2_LETTER 'Z' + +#if N_AXIS > 3 + #if AXIS_REMAP_ABC2UVW + #define AXIS3_LETTER 'U' + #elif !defined(AXIS3_LETTER) + #define AXIS3_LETTER 'A' + #elif !IS_AXIS_LETTER_VALID(AXIS3_LETTER) + #error "Illegal axis letter assigned!" + #endif +#else + #define AXIS3_LETTER 0 +#endif + +#if N_AXIS > 4 + #if AXIS_REMAP_ABC2UVW + #define AXIS4_LETTER 'V' + #elif !defined(AXIS4_LETTER) + #define AXIS4_LETTER 'B' + #elif !IS_AXIS_LETTER_VALID(AXIS4_LETTER) + #error "Illegal axis letter assigned!" + #endif +#else + #define AXIS4_LETTER 0 +#endif + +#if N_AXIS > 5 + #if AXIS_REMAP_ABC2UVW + #define AXIS5_LETTER 'W' + #elif !defined(AXIS5_LETTER) + #define AXIS5_LETTER 'C' + #elif !IS_AXIS_LETTER_VALID(AXIS5_LETTER) + #error "Illegal axis letter assigned!" + #endif +#else + #define AXIS5_LETTER 0 +#endif + +#if N_AXIS > 6 + #if !defined(AXIS6_LETTER) + #define AXIS6_LETTER 'U' + #elif !IS_AXIS_LETTER_VALID(AXIS6_LETTER) + #error "Illegal axis letter assigned!" + #endif +#else + #define AXIS6_LETTER 0 +#endif + +#if N_AXIS > 7 + #if !defined(AXIS7_LETTER) + #define AXIS7_LETTER 'V' + #elif !IS_AXIS_LETTER_VALID(AXIS7_LETTER) + #error "Illegal axis letter assigned!" + #endif +#else + #define AXIS7_LETTER 0 +#endif + +#if N_AXIS == 4 +#define AXIS_LETTER_TO_IDX(c) AXIS3_IDX +#elif N_AXIS == 5 +#define AXIS_LETTER_TO_IDX(c) \ +(c == AXIS3_LETTER ? AXIS3_IDX : \ +(c == AXIS4_LETTER ? AXIS4_IDX : -1)) +#elif N_AXIS == 6 +#define AXIS_LETTER_TO_IDX(c) \ +(c == AXIS3_LETTER ? AXIS3_IDX : \ +(c == AXIS4_LETTER ? AXIS4_IDX : \ +(c == AXIS5_LETTER ? AXIS5_IDX : -1))) +#elif N_AXIS == 7 +#define AXIS_LETTER_TO_IDX(c) \ +(c == AXIS3_LETTER ? AXIS3_IDX : \ +(c == AXIS4_LETTER ? AXIS4_IDX : \ +(c == AXIS5_LETTER ? AXIS5_IDX : \ +(c == AXIS6_LETTER ? AXIS6_IDX : -1)))) +#elif N_AXIS == 8 +#define AXIS_LETTER_TO_IDX(c) \ +(c == AXIS3_LETTER ? AXIS3_IDX : \ +(c == AXIS4_LETTER ? AXIS4_IDX : \ +(c == AXIS5_LETTER ? AXIS5_IDX : \ +(c == AXIS6_LETTER ? AXIS6_IDX : \ +(c == AXIS7_LETTER ? AXIS7_IDX : -1))))) +#endif + +#if IS_AXIS_LETTER('A') +#define A_AXIS AXIS_LETTER_TO_IDX('A') +#define A_AXIS_BIT bit(A_AXIS) +#endif + +#if IS_AXIS_LETTER('B') +#define B_AXIS AXIS_LETTER_TO_IDX('B') +#define B_AXIS_BIT bit(B_AXIS) +#endif + +#if IS_AXIS_LETTER('C') +#define C_AXIS AXIS_LETTER_TO_IDX('C') +#define C_AXIS_BIT bit(C_AXIS) +#endif + +#if !LATHE_UVW_OPTION + +#if IS_AXIS_LETTER('U') +#define U_AXIS AXIS_LETTER_TO_IDX('U') +#define U_AXIS_BIT bit(U_AXIS) +#endif + +#if IS_AXIS_LETTER('V') +#define V_AXIS AXIS_LETTER_TO_IDX('V') +#define V_AXIS_BIT bit(V_AXIS) +#endif + +#if IS_AXIS_LETTER('W') +#define W_AXIS AXIS_LETTER_TO_IDX('W') +#define W_AXIS_BIT bit(W_AXIS) +#endif + +#endif + typedef union { uint8_t mask; uint8_t bits; @@ -127,12 +250,38 @@ typedef union { struct { uint8_t x :1, y :1, - z :1, - a :1, - b :1, - c :1, - u :1, - v :1; + z :1 +#if N_AXIS > 3 + #ifdef A_AXIS + , a :1 + #endif + #ifdef B_AXIS + , b :1 + #endif + #ifdef C_AXIS + , c :1 + #endif + #ifdef U_AXIS + , u :1 + #endif + #ifdef V_AXIS + , v :1 + #endif + #ifdef W_AXIS + , w :1 + #endif +#endif +; + }; + struct { + uint8_t a0 :1, + a1 :1, + a2 :1, + a3 :1, + a4 :1, + a5 :1, + a6 :1, + a7 :1; }; } axes_signals_t; @@ -143,64 +292,62 @@ typedef union { float x; float y; float z; -#ifdef A_AXIS - float a; -#endif -#ifdef B_AXIS - float b; -#endif -#ifdef C_AXIS - float c; -#endif -#ifdef U_AXIS - float u; -#endif -#ifdef V_AXIS - float v; -#endif - }; - struct { - float m0; - float m1; - float m2; #if N_AXIS > 3 - float m3; -#endif -#if N_AXIS > 4 - float m4; -#endif -#if N_AXIS > 5 - float m5; -#endif -#if N_AXIS > 6 - float m6; -#endif -#if N_AXIS == 8 - float m7; + #ifdef A_AXIS + float a; + #endif + #ifdef B_AXIS + float b; + #endif + #ifdef C_AXIS + float c; + #endif + #ifdef U_AXIS + float u; + #endif + #ifdef V_AXIS + float v; + #endif + #ifdef W_AXIS + float w; + #endif #endif }; } coord_data_t; +//! Coordinate system data. +typedef struct { + coord_data_t coord; +#ifdef ROTATION_ENABLE + float rotation; +#endif +} coord_system_data_t; + typedef union { int32_t value[N_AXIS]; struct { int32_t x; int32_t y; int32_t z; -#ifdef A_AXIS +#if N_AXIS > 3 + #ifdef B_AXIS int32_t a; -#endif -#ifdef B_AXIS + #endif + #ifdef B_AXIS int32_t b; -#endif -#ifdef C_AXIS + #endif + #ifdef C_AXIS int32_t c; -#endif -#ifdef U_AXIS + #endif + #ifdef U_AXIS int32_t u; -#endif -#ifdef V_AXIS + #endif + #ifdef V_AXIS int32_t v; + #endif + #ifdef W_AXIS + int32_t w; + #endif #endif }; } mpos_t; @@ -213,6 +360,25 @@ typedef union { }; } point_2d_t; +typedef union { + float values[3]; + struct { + float x; + float y; + float z; + }; +} point_3d_t; + +//! Axis index to plane assignment. +typedef union { + uint8_t axis[3]; + struct { + uint8_t axis_0; + uint8_t axis_1; + uint8_t axis_linear; + }; +} plane_t; + #pragma pack(push, 1) //! \brief Limit switches struct, consists of four packed axes_signals_t structs in 32 bits. @@ -335,6 +501,8 @@ bool delay_sec (float seconds, delaymode_t mode); float convert_delta_vector_to_unit_vector(float *vector); +void rotate (coord_data_t *pt, plane_t plane, float angle /*rad*/); + // parse ISO8601 datetime struct tm *get_datetime (const char *s); diff --git a/nvs.h b/nvs.h index e89b05c..e48fc89 100644 --- a/nvs.h +++ b/nvs.h @@ -42,14 +42,14 @@ Must be >= NVS_SIZE. #define NVS_CRC_BYTES 2 #endif -#define NVS_SIZE_PARAMETERS ((sizeof(coord_data_t) + NVS_CRC_BYTES) * N_CoordinateSystems) +#define NVS_SIZE_PARAMETERS ((sizeof(coord_system_data_t) + NVS_CRC_BYTES) * N_CoordinateSystems) #define NVS_SIZE_BUILD_INFO (sizeof(stored_line_t) + NVS_CRC_BYTES) #define NVS_SIZE_STARTUP_BLOCK (N_STARTUP_LINE * (sizeof(stored_line_t) + NVS_CRC_BYTES)) /*! \brief Number of bytes at the start of the NVS area reserved for core settings and parameters. Minimum 1024 bytes required, more if > 5 axes enabled. */ -#if N_AXIS > 5 +#if N_AXIS > 5 || (N_AXIS > 4 && defined(ROTATION_ENABLE)) #define GRBL_NVS_END (NVS_ADDR_GLOBAL + ((sizeof(settings_t) + NVS_CRC_BYTES + 4) & 0xFFFC) + NVS_SIZE_PARAMETERS + NVS_SIZE_BUILD_INFO + NVS_SIZE_STARTUP_BLOCK + 1) #else #define GRBL_NVS_END 1023 @@ -69,7 +69,7 @@ __NOTE:__ 1024 bytes of persistent storage is the minimum required. */ ///@{ #define NVS_ADDR_GLOBAL 1U -#if N_AXIS > 5 +#if N_AXIS > 5 || (N_AXIS > 4 && defined(ROTATION_ENABLE)) #define NVS_ADDR_PARAMETERS ((sizeof(settings_t) + NVS_CRC_BYTES + 4) & 0xFFFC) // align to word boundary #else #define NVS_ADDR_PARAMETERS 512U diff --git a/nvs_buffer.c b/nvs_buffer.c index 0ea5bff..accc60c 100644 --- a/nvs_buffer.c +++ b/nvs_buffer.c @@ -58,7 +58,7 @@ typedef struct { #define NVS_GROUP_STARTUP 3 #define NVS_GROUP_BUILD 4 -#define PARAMETER_ADDR(n) (NVS_ADDR_PARAMETERS + n * (sizeof(coord_data_t) + NVS_CRC_BYTES)) +#define PARAMETER_ADDR(n) (NVS_ADDR_PARAMETERS + n * (sizeof(coord_system_data_t) + NVS_CRC_BYTES)) #define STARTLINE_ADDR(n) (NVS_ADDR_STARTUP_BLOCK + n * (sizeof(stored_line_t) + NVS_CRC_BYTES)) #if N_TOOLS #define TOOL_ADDR(n) (NVS_ADDR_TOOL_TABLE + n * (sizeof(tool_data_t) + NVS_CRC_BYTES)) @@ -352,8 +352,8 @@ void nvs_buffer_sync_physical (void) idx = N_CoordinateSystems; if(settings_dirty.coord_data) do { if(bit_istrue(settings_dirty.coord_data, bit(idx))) { - offset = NVS_ADDR_PARAMETERS + idx * (sizeof(coord_data_t) + NVS_CRC_BYTES); - if(physical_nvs.memcpy_to_nvs(offset, (uint8_t *)(nvsbuffer.addr + offset), sizeof(coord_data_t) + NVS_CRC_BYTES, false) == NVS_TransferResult_OK) + offset = NVS_ADDR_PARAMETERS + idx * (sizeof(coord_system_data_t) + NVS_CRC_BYTES); + if(physical_nvs.memcpy_to_nvs(offset, (uint8_t *)(nvsbuffer.addr + offset), sizeof(coord_system_data_t) + NVS_CRC_BYTES, false) == NVS_TransferResult_OK) bit_false(settings_dirty.coord_data, bit(idx)); } } while(idx--); @@ -425,7 +425,7 @@ void nvs_memmap (void) strcat(buf, " "); strcat(buf, uitoa(NVS_SIZE_PARAMETERS)); strcat(buf, " "); - strcat(buf, uitoa(NVS_ADDR_PARAMETERS + N_CoordinateSystems * (sizeof(coord_data_t) + NVS_CRC_BYTES))); + strcat(buf, uitoa(NVS_ADDR_PARAMETERS + N_CoordinateSystems * (sizeof(coord_system_data_t) + NVS_CRC_BYTES))); report_message(buf, Message_Plain); strcpy(buf, "Startup block: "); diff --git a/nvs_buffer.h b/nvs_buffer.h index 0eb0444..0d8423d 100644 --- a/nvs_buffer.h +++ b/nvs_buffer.h @@ -6,18 +6,18 @@ Copyright (c) 2017-2023 Terje Io Copyright (c) 2009-2011 Simen Svale Skogsrud - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _NVS_BUFFER_H_ diff --git a/override.c b/override.c index 490592b..4e54e2e 100644 --- a/override.c +++ b/override.c @@ -7,18 +7,18 @@ Copyright (c) 2017-2023 Terje Io - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #include "grbl.h" diff --git a/override.h b/override.h index 88ca449..165d9ec 100644 --- a/override.h +++ b/override.h @@ -7,18 +7,18 @@ Copyright (c) 2016-2023 Terje Io - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _OVERRIDE_H_ diff --git a/pid.c b/pid.c index af23915..fbc465a 100644 --- a/pid.c +++ b/pid.c @@ -3,24 +3,24 @@ PID algorithm for closed loop control - NOTE: not referenced in the core grbl code + NOTE: not referenced in the core grblHAL code Part of grblHAL Copyright (c) 2020-2021 Terje Io - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #include diff --git a/pid.h b/pid.h index a3b27b0..8cb4c3c 100644 --- a/pid.h +++ b/pid.h @@ -3,24 +3,24 @@ PID algorithm for closed loop control - NOTE: not referenced in the core grbl code + NOTE: not referenced in the core grblHAL code Part of grblHAL Copyright (c) 2020-2023 Terje Io - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _PID_H_ diff --git a/pin_bits_masks.h b/pin_bits_masks.h index 60c9b8a..6de9de0 100644 --- a/pin_bits_masks.h +++ b/pin_bits_masks.h @@ -330,10 +330,12 @@ static inline void aux_ctrl_claim_ports (aux_claim_explicit_ptr aux_claim_explic pin_cap_t cap = { .irq_mode = aux_ctrl[idx].irq_mode, .claimable = On }; - if(aux_ctrl[idx].gpio.pin == 0xFE) // Toolsetter and Probe2 - ioports_enumerate(Port_Digital, Port_Input, cap, __find_in_port, (void *)&aux_ctrl[idx]); + // Toolsetter and Probe2 + if(aux_ctrl[idx].gpio.pin == 0xFE && ioports_enumerate(Port_Digital, Port_Input, cap, __find_in_port, (void *)&aux_ctrl[idx])) + aux_claim_explicit(&aux_ctrl[idx]); + #ifdef STM32_PLATFORM - if(aux_ctrl[idx].irq_mode == IRQ_Mode_None && !(aux_ctrl[idx].function == Input_Probe || aux_ctrl[idx].function == Input_LimitsOverride)) + if(aux_ctrl[idx].irq_mode == IRQ_Mode_None && !(aux_ctrl_is_probe(aux_ctrl[idx].function) || aux_ctrl[idx].function == Input_LimitsOverride)) continue; #endif if(aux_ctrl[idx].gpio.pin == 0xFF) { @@ -617,7 +619,72 @@ static inline void aux_ctrl_claim_out_ports (aux_claim_explicit_out_ptr aux_clai #define DEVICES_IRQ_MASK_SUM (SPI_IRQ_BIT+SPINDLE_INDEX_BIT+QEI_A_BIT+QEI_B_BIT+SD_DETECT_BIT) #endif -// Auxillary input signals +#ifdef STM32_PLATFORM + +// Used for validating pins that requires IRQ capabilities + +#ifdef RESET_PIN +#define RESET_BIT (1<condition.no_feed_override) { - if(nominal_speed > block->rapid_rate) - nominal_speed = block->rapid_rate; + if(nominal_speed > block->rapid_rate) + nominal_speed = block->rapid_rate; nominal_speed *= (0.01f * (float)sys.override.feed_rate); - } + } if(nominal_speed > block->rapid_rate) nominal_speed = block->rapid_rate; } @@ -424,6 +424,10 @@ bool plan_buffer_line (float *target, plan_line_data_t *pl_data) block->offset_id = pl_data->offset_id; block->output_commands = pl_data->output_commands; block->message = pl_data->message; +#if PLANNER_ADD_MOTION_MODE + if((block->motion_mode = pl_data->motion_mode) == MotionMode_Seek && !block->condition.rapid_motion) + block->motion_mode = MotionMode_Linear; +#endif memcpy(block->target_mm, target, sizeof(float) * N_AXIS); // Copy position data based on type of motion being planned. @@ -528,24 +532,28 @@ bool plan_buffer_line (float *target, plan_line_data_t *pl_data) #endif block->millimeters = convert_delta_vector_to_unit_vector(unit_vec); -#if ENABLE_JERK_ACCELERATION - block->max_acceleration = limit_acceleration_by_axis_maximum(unit_vec); - block->jerk = limit_jerk_by_axis_maximum(unit_vec); -#else - block->acceleration = limit_acceleration_by_axis_maximum(unit_vec); +#if ENABLE_ACCELERATION_PROFILES // recalculate the acceleration limits when enabled. +// block->acceleration_factor = pl_data->acceleration_factor; #endif +#if ENABLE_JERK_ACCELERATION + if((block->condition.jerk = !(block->condition.jog_motion || block->condition.system_motion || block->spindle.state.synchronized))) { + block->max_acceleration = limit_acceleration_by_axis_maximum(unit_vec); + block->jerk = limit_jerk_by_axis_maximum(unit_vec); + #if ENABLE_ACCELERATION_PROFILES + block->max_acceleration *= pl_data->acceleration_factor; + block->jerk *= pl_data->acceleration_factor; + #endif + } else +#endif // ENABLE_JERK_ACCELERATION + { + block->acceleration = limit_acceleration_by_axis_maximum(unit_vec); +#if ENABLE_ACCELERATION_PROFILES + block->acceleration *= pl_data->acceleration_factor; +#endif + } block->rapid_rate = limit_max_rate_by_axis_maximum(unit_vec); #ifdef KINEMATICS_API block->rate_multiplier = pl_data->rate_multiplier; -#endif -#if ENABLE_ACCELERATION_PROFILES // recalculate the acceleration limits when enabled. - block->acceleration_factor = pl_data->acceleration_factor; -#if ENABLE_JERK_ACCELERATION - block->max_acceleration *= block->acceleration_factor; - block->jerk *= block->acceleration_factor; -#else - block->acceleration *= block->acceleration_factor; -#endif #endif // Store programmed rate. @@ -556,23 +564,28 @@ bool plan_buffer_line (float *target, plan_line_data_t *pl_data) if (block->condition.inverse_time) block->programmed_rate *= block->millimeters; } + #if ENABLE_JERK_ACCELERATION + // Calculate effective acceleration over block. Since jerk acceleration takes longer to execute due to ramp up and // ramp down of the acceleration at the start and end of a ramp we need to adjust the acceleration value the planner // uses so it still calculates reasonable entry speeds, exit speeds and times to decelerate/accelerate. // 2 general cases emerge: - // -slow speed regime: uncomplete jerk ramp (max_acceleration is not reached) + // -slow speed regime: incomplete jerk ramp (max_acceleration is not reached) // -high speed regime: complete jerk ramp + time at max_axcel to reach desired programmed_rates // Profiles are calculated as symmetrical (calculate to 1/2 programmed rate, then double) - float time_to_max_accel = block->max_acceleration / block->jerk; // unit: min - time it takes to reach max acceleration - float speed_after_jerkramp = 0.5f * block->jerk * time_to_max_accel * time_to_max_accel; // unit: mm / min - velocity after one completed jerk ramp up - Vt = V0 + A0T + 1/2 jerk*T - if(0.5f * block->programmed_rate > speed_after_jerkramp) - // Profile time = 2x (1 complete jerk ramp + additional time at max_accel to reach desired speed) - block->acceleration = block->programmed_rate / (2.0f *(time_to_max_accel + (0.5f * block->programmed_rate - speed_after_jerkramp) / block->max_acceleration)); - else - // Max Accel is not reached. time_to_halfvelocity = sqrt( 0.5 programmed_rate * 2 / jerk) -> derived from Vt = V0 + A0T + 1/2 jerk*T (v0 and a0t == 0 in this case) - block->acceleration = block->programmed_rate / (2.0f * sqrt(block->programmed_rate / block->jerk)); -#endif + if(block->condition.jerk) { + float time_to_max_accel = block->max_acceleration / block->jerk; // unit: min - time it takes to reach max acceleration + float speed_after_jerkramp = 0.5f * block->jerk * time_to_max_accel * time_to_max_accel; // unit: mm / min - velocity after one completed jerk ramp up - Vt = V0 + A0T + 1/2 jerk*T + if(0.5f * block->programmed_rate > speed_after_jerkramp) + // Profile time = 2x (1 complete jerk ramp + additional time at max_accel to reach desired speed) + block->acceleration = block->programmed_rate / (2.0f * (time_to_max_accel + (0.5f * block->programmed_rate - speed_after_jerkramp) / block->max_acceleration)); + else + // Max Accel is not reached. time_to_halfvelocity = sqrt(0.5 * programmed_rate * 2 / jerk) -> derived from Vt = V0 + A0T + 1/2 jerk*T (v0 and a0t == 0 in this case) + block->acceleration = block->programmed_rate / (2.0f * sqrt(block->programmed_rate / block->jerk)); + } + +#endif // ENABLE_JERK_ACCELERATION // TODO: Need to check this method handling zero junction speeds when starting from rest. if ((block_buffer_head == block_buffer_tail) || (block->condition.system_motion)) { @@ -594,8 +607,8 @@ bool plan_buffer_line (float *target, plan_line_data_t *pl_data) // from path, but used as a robust way to compute cornering speeds, as it takes into account the // nonlinearities of both the junction angle and junction velocity. // - // NOTE: If the junction deviation value is finite, Grbl executes the motions in an exact path - // mode (G61). If the junction deviation value is zero, Grbl will execute the motion in an exact + // NOTE: If the junction deviation value is finite, grblHAL executes the motions in an exact path + // mode (G61). If the junction deviation value is zero, grblHAL will execute the motion in an exact // stop mode (G61.1) manner. In the future, if continuous mode (G64) is desired, the math here // is exactly the same. Instead of motioning all the way to junction point, the machine will // just follow the arc circle defined here. The Arduino doesn't have the CPU cycles to perform diff --git a/planner.h b/planner.h index 1e2f5ef..5118058 100644 --- a/planner.h +++ b/planner.h @@ -39,7 +39,12 @@ typedef union { target_valid :1, target_validated :1, probing_toolsetter :1, +#if ENABLE_JERK_ACCELERATION + jerk :1, + unassigned :3; +#else unassigned :4; +#endif coolant_state_t coolant; }; } planner_cond_t; @@ -64,6 +69,9 @@ typedef union { #endif #ifdef V_AXIS uint32_t v; +#endif +#ifdef W_AXIS + uint32_t w; #endif }; } steps_t; @@ -81,7 +89,7 @@ typedef struct plan_block { // Block condition data to ensure correct execution depending on states and overrides. gc_override_flags_t overrides; // Block bitfield variable for overrides planner_cond_t condition; // Block bitfield variable defining block run conditions. Copied from pl_line_data. - int32_t line_number; // Block line number for real-time reporting. Copied from pl_line_data. + uint32_t line_number; // Block line number for real-time reporting. Copied from pl_line_data. float target_mm[N_AXIS]; // Block target end location in mm for real-time reporting of distance to go. // Fields used by the motion planner to manage acceleration. Some of these values may be updated @@ -105,9 +113,12 @@ typedef struct plan_block { float rate_multiplier; // Rate multiplier of this block. #endif #if ENABLE_ACCELERATION_PROFILES - float acceleration_factor; // Stores the currently used acceleration factor. +// float acceleration_factor; // Stores the currently used acceleration factor. #endif - // Stored spindle speed data used by spindle overrides and resuming methods. +#if PLANNER_ADD_MOTION_MODE + motion_mode_t motion_mode; +#endif +// Stored spindle speed data used by spindle overrides and resuming methods. spindle_t spindle; // Block spindle parameters. Copied from pl_line_data. char *message; // Message to be displayed when block is executed. @@ -128,12 +139,15 @@ typedef struct { #if ENABLE_PATH_BLENDING float path_tolerance; //!< Path blending tolerance. float cam_tolerance; //!< Naive CAM tolerance. +#endif +#if PLANNER_ADD_MOTION_MODE + motion_mode_t motion_mode; #endif spindle_t spindle; // Desired spindle parameters, such as RPM, through line motion. planner_cond_t condition; // Bitfield variable to indicate planner conditions. See defines above. gc_override_flags_t overrides; // Block bitfield variable for overrides offset_id_t offset_id; - int32_t line_number; // Desired line number to report when executing. + uint32_t line_number; // Desired line number to report when executing. // void *parameters; // TODO: pointer to extra parameters, for canned cycles and threading? char *message; // Message to be displayed when block is executed. output_command_t *output_commands; diff --git a/plugins.h b/plugins.h index d38ca29..63c83a8 100644 --- a/plugins.h +++ b/plugins.h @@ -3,7 +3,7 @@ Some data structures and function declarations for plugins that require driver code - These are NOT referenced in the core grbl code + These are NOT referenced in the core grblHAL code Part of grblHAL @@ -112,6 +112,7 @@ typedef struct { const char *interface; bool is_ethernet; bool link_up; + bool dhcp; // TODO: move to network_services_t in next settings revision. uint16_t mbps; char mac[18]; char mqtt_client_id[18]; @@ -167,6 +168,9 @@ typedef enum { Encoder_MPG_A, Encoder_MPG_B, Encoder_MPG_C, + Encoder_MPG_U, + Encoder_MPG_V, + Encoder_MPG_W, Encoder_Spindle_Position } encoder_mode_t; diff --git a/plugins_init.h b/plugins_init.h index 421ad6a..cd66bd0 100644 --- a/plugins_init.h +++ b/plugins_init.h @@ -3,7 +3,7 @@ Calls the init function of enabled plugins, may be included at the end of the drivers driver_init() implementation. - These are NOT referenced in the core grbl code + These are NOT referenced in the core grblHAL code Part of grblHAL @@ -166,7 +166,7 @@ embroidery_init(); #endif -#if RGB_LED_ENABLE +#if RGB_LED_ENABLE > 1 extern void rgb_led_init (void); rgb_led_init(); #endif @@ -239,10 +239,14 @@ #endif #if ATCI_ENABLE - extern void atci_init(void); + extern void atci_init (void); atci_init(); #endif +#if M800_ENABLE + extern void keyway_init (void); + keyway_init(); +#endif // End third party plugin definitions. diff --git a/protocol.c b/protocol.c index e12db47..ef1c084 100644 --- a/protocol.c +++ b/protocol.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2025 Terje Io + Copyright (c) 2017-2026 Terje Io Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -388,7 +388,7 @@ void protocol_auto_cycle_start (void) // from various check points in the main program, primarily where there may be a while loop waiting // for a buffer to clear space or any point where the execution time from the last check point may // be more than a fraction of a second. This is a way to execute realtime commands asynchronously -// (aka multitasking) with grbl's g-code parsing and planning functions. This function also serves +// (aka multitasking) with grblHAL's g-code parsing and planning functions. This function also serves // as an interface for the interrupts to set the system realtime flags, where only the main program // handles them, removing the need to define more computationally-expensive volatile variables. This // also provides a controlled way to execute certain tasks without having two or more instances of @@ -499,7 +499,7 @@ bool protocol_exec_rt_system (void) if(bit_istrue(sys.rt_exec_state, EXEC_STATUS_REPORT)) { system_clear_exec_state_flag(EXEC_STATUS_REPORT); - report_realtime_status(hal.stream.write_all); + report_realtime_status(hal.stream.write_all, system_get_rt_report_flags()); } protocol_poll_cmd(); @@ -599,10 +599,10 @@ bool protocol_exec_rt_system (void) // Execute and print status to output stream if (rt_exec & EXEC_STATUS_REPORT) - report_realtime_status(hal.stream.write_all); + report_realtime_status(hal.stream.write_all, system_get_rt_report_flags()); if(rt_exec & EXEC_GCODE_REPORT) - report_gcode_modes(); + report_gcode_modes(hal.stream.write); if(rt_exec & EXEC_TLO_REPORT) report_tool_offsets(); @@ -860,16 +860,7 @@ ISR_CODE bool ISR_FUNC(protocol_enqueue_realtime_command)(uint8_t c) #endif case CMD_STATUS_REPORT_ALL: // Add all statuses to report - { - report_tracking_flags_t report; - - report.value = (uint32_t)Report_All; - report.tool_offset = sys.report.tool_offset; - report.m66result = sys.var5399 > -2; - report.probe_id = !!hal.probe.select; - - system_add_rt_report((report_tracking_t)report.value); - } + system_add_rt_report(report_get_rt_flags_all().value); system_set_exec_state_flag(EXEC_STATUS_REPORT); drop = true; break; diff --git a/protocol.h b/protocol.h index 44423ea..008b06d 100644 --- a/protocol.h +++ b/protocol.h @@ -1,5 +1,5 @@ /* - protocol.h - controls Grbl execution protocol and procedures + protocol.h - controls grblHAL execution protocol and procedures Part of grblHAL diff --git a/report.c b/report.c index 2b7e512..276804e 100644 --- a/report.c +++ b/report.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2025 Terje Io + Copyright (c) 2017-2026 Terje Io Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC grblHAL is free software: you can redistribute it and/or modify @@ -598,7 +598,7 @@ status_code_t report_named_ngc_parameter (char *arg) void report_ngc_parameters (void) { uint_fast8_t idx; - float coord_data[N_AXIS]; + coord_system_data_t offset; if(gc_state.modal.scaling_active) { hal.stream.write("[G51:"); @@ -606,16 +606,16 @@ void report_ngc_parameters (void) hal.stream.write("]" ASCII_EOL); } - for (idx = 0; idx < N_CoordinateSystems; idx++) { + for(idx = 0; idx < N_CoordinateSystems; idx++) { - if (!(settings_read_coord_data((coord_system_id_t)idx, &coord_data))) { + if(!(settings_read_coord_data((coord_system_id_t)idx, &offset))) { grbl.report.status_message(Status_SettingReadFail); return; } hal.stream.write("[G"); - switch (idx) { + switch(idx) { case CoordinateSystem_G28: hal.stream.write("28"); @@ -635,14 +635,20 @@ void report_ngc_parameters (void) if(idx != CoordinateSystem_G92) { hal.stream.write(":"); - hal.stream.write(get_axis_values(coord_data)); + hal.stream.write(get_axis_values(offset.coord.values)); +#ifdef ROTATION_ENABLE + if(idx < N_WorkCoordinateSystems) { + hal.stream.write(":"); + hal.stream.write(ftoa(offset.rotation * DEGRAD, 2)); + } +#endif hal.stream.write("]" ASCII_EOL); } } // Print G92, G92.1 which are not persistent in memory hal.stream.write("92:"); - hal.stream.write(get_axis_values(gc_state.g92_coord_offset)); + hal.stream.write(get_axis_values(gc_state.g92_offset.coord.values)); hal.stream.write("]" ASCII_EOL); tool_data_t *tool_data; @@ -695,66 +701,83 @@ static inline bool is_g92_active (void) do { idx--; - active = !(gc_state.g92_coord_offset[idx] == 0.0f || gc_state.g92_coord_offset[idx] == -0.0f); + active = !(gc_state.g92_offset.coord.values[idx] == 0.0f || gc_state.g92_offset.coord.values[idx] == -0.0f); } while(idx && !active); return active; } -// Print current gcode parser mode state -void report_gcode_modes (void) +// Convert motion mode (G0, G1, ...) to string. +static char *motionmode_to_str (char *buf, motion_mode_t mode) { - hal.stream.write("[GC:G"); - if (gc_state.modal.motion >= MotionMode_ProbeToward) { - hal.stream.write("38."); - hal.stream.write(uitoa((uint32_t)(gc_state.modal.motion - (MotionMode_ProbeToward - 2)))); - } else - hal.stream.write(uitoa((uint32_t)gc_state.modal.motion)); + strcpy(buf, "G"); - hal.stream.write(" "); - hal.stream.write(gc_coord_system_to_str(gc_state.modal.coord_system.id)); + if(mode == MotionMode_QuadraticSpline || mode == MotionMode_RigidTapping) { + strcat(buf, uitoa(mode / 10)); + strcat(buf, ".1"); + } else if(mode >= MotionMode_ProbeToward) { + strcat(buf, "38."); + strcat(buf, uitoa((uint32_t)(mode - (MotionMode_ProbeToward - 2)))); + } else + strcat(buf, uitoa((uint32_t)mode)); + + return buf; +} + +// Print current gcode parser mode state +void report_gcode_modes (stream_write_ptr stream_write) +{ + stream_write("[GC:"); + stream_write(motionmode_to_str(buf, gc_state.modal.motion)); + stream_write(" "); + stream_write(gc_coord_system_to_str(gc_state.modal.g5x_offset.id)); #if COMPATIBILITY_LEVEL < 10 if(is_g92_active()) - hal.stream.write(" G92"); + stream_write(" G92"); #endif if(settings.mode == Mode_Lathe) - hal.stream.write(gc_state.modal.diameter_mode ? " G7" : " G8"); + stream_write(gc_state.modal.diameter_mode ? " G7" : " G8"); - hal.stream.write(" G"); - hal.stream.write(uitoa((uint32_t)(gc_state.modal.plane_select + 17))); + stream_write(" G"); + stream_write(uitoa((uint32_t)(gc_state.modal.plane_select + 17))); - hal.stream.write(gc_state.modal.units_imperial ? " G20" : " G21"); + stream_write(gc_state.modal.units_imperial ? " G20" : " G21"); - hal.stream.write(gc_state.modal.distance_incremental ? " G91" : " G90"); +#if NGC_PARAMETERS_ENABLE + if(gc_state.g66_args) + stream_write(" G66"); +#endif - hal.stream.write(" G"); - hal.stream.write(uitoa((uint32_t)(93 + (gc_state.modal.feed_mode == FeedMode_UnitsPerRev ? 2 : gc_state.modal.feed_mode ^ 1)))); + stream_write(gc_state.modal.distance_incremental ? " G91" : " G90"); + + stream_write(" G"); + stream_write(uitoa((uint32_t)(93 + (gc_state.modal.feed_mode == FeedMode_UnitsPerRev ? 2 : gc_state.modal.feed_mode ^ 1)))); if(settings.mode == Mode_Lathe && gc_spindle_get(0)->hal->cap.variable) - hal.stream.write(gc_spindle_get(0)->rpm_mode == SpindleSpeedMode_RPM ? " G97" : " G96"); + stream_write(gc_spindle_get(0)->rpm_mode == SpindleSpeedMode_RPM ? " G97" : " G96"); #if COMPATIBILITY_LEVEL < 10 if(gc_state.modal.tool_offset_mode == ToolLengthOffset_Cancel) - hal.stream.write(" G49"); + stream_write(" G49"); else { - hal.stream.write(" G43"); + stream_write(" G43"); if(gc_state.modal.tool_offset_mode != ToolLengthOffset_Enable) - hal.stream.write(gc_state.modal.tool_offset_mode == ToolLengthOffset_EnableDynamic ? ".1" : ".2"); + stream_write(gc_state.modal.tool_offset_mode == ToolLengthOffset_EnableDynamic ? ".1" : ".2"); } - hal.stream.write(gc_state.modal.retract_mode == CCRetractMode_RPos ? " G99" : " G98"); + stream_write(gc_state.modal.retract_mode == CCRetractMode_RPos ? " G99" : " G98"); if(gc_state.modal.scaling_active) { - hal.stream.write(" G51:"); + stream_write(" G51:"); axis_signals_tostring(buf, gc_get_g51_state()); - hal.stream.write(buf); + stream_write(buf); } else - hal.stream.write(" G50"); + stream_write(" G50"); #endif @@ -763,23 +786,23 @@ void report_gcode_modes (void) switch (gc_state.modal.program_flow) { case ProgramFlow_Paused: - hal.stream.write(" M0"); + stream_write(" M0"); break; case ProgramFlow_OptionalStop: - hal.stream.write(" M1"); + stream_write(" M1"); break; case ProgramFlow_CompletedM2: - hal.stream.write(" M2"); + stream_write(" M2"); break; case ProgramFlow_CompletedM30: - hal.stream.write(" M30"); + stream_write(" M30"); break; case ProgramFlow_CompletedM60: - hal.stream.write(" M60"); + stream_write(" M60"); break; default: @@ -787,42 +810,42 @@ void report_gcode_modes (void) } } - hal.stream.write(gc_spindle_get(0)->state.on ? (gc_spindle_get(0)->state.ccw ? " M4" : " M3") : " M5"); + stream_write(gc_spindle_get(0)->state.on ? (gc_spindle_get(0)->state.ccw ? " M4" : " M3") : " M5"); if(gc_state.tool_change) - hal.stream.write(" M6"); + stream_write(" M6"); if (gc_state.modal.coolant.value) { if (gc_state.modal.coolant.mist) - hal.stream.write(" M7"); + stream_write(" M7"); if (gc_state.modal.coolant.flood) - hal.stream.write(" M8"); + stream_write(" M8"); } else - hal.stream.write(" M9"); + stream_write(" M9"); if (sys.override.control.feed_rates_disable) - hal.stream.write(" M50"); + stream_write(" M50"); if (sys.override.control.spindle_rpm_disable) - hal.stream.write(" M51"); + stream_write(" M51"); if (sys.override.control.feed_hold_disable) - hal.stream.write(" M53"); + stream_write(" M53"); if (settings.parking.flags.enable_override_control && sys.override.control.parking_disable) - hal.stream.write(" M56"); + stream_write(" M56"); - hal.stream.write(appendbuf(2, " T", uitoa((uint32_t)gc_state.tool->tool_id))); + stream_write(appendbuf(2, " T", uitoa((uint32_t)gc_state.tool->tool_id))); - hal.stream.write(appendbuf(2, " F", get_rate_value(gc_state.feed_rate))); + stream_write(appendbuf(2, " F", get_rate_value(gc_state.feed_rate))); if(gc_spindle_get(0)->hal->cap.variable) - hal.stream.write(appendbuf(2, " S", ftoa(gc_spindle_get(0)->rpm, N_DECIMAL_RPMVALUE))); + stream_write(appendbuf(2, " S", ftoa(gc_spindle_get(0)->rpm, N_DECIMAL_RPMVALUE))); - hal.stream.write("]" ASCII_EOL); + stream_write("]" ASCII_EOL); } // Prints specified startup line @@ -1139,12 +1162,17 @@ void report_echo_line_received (char *line) #if N_SYS_SPINDLE == 1 && N_SPINDLE > 1 +typedef struct { + spindle_id_t spindle_id; + stream_write_ptr stream_write; +} spindle_r_t; + static bool report_spindle_num (spindle_info_t *spindle, void *data) { bool ok; - if((ok = spindle->id == *((spindle_id_t *)data))) - hal.stream.write_all(appendbuf(2, "|S:", uitoa((uint32_t)spindle->num))); + if((ok = spindle->id == ((spindle_r_t *)data)->spindle_id)) + ((spindle_r_t *)data)->stream_write(appendbuf(2, "|S:", uitoa((uint32_t)spindle->num))); return ok; } @@ -1156,13 +1184,13 @@ static bool report_spindle_num (spindle_info_t *spindle, void *data) // specific needs, but the desired real-time data report must be as short as possible. This is // requires as it minimizes the computational overhead and allows grblHAL to keep running smoothly, // especially during g-code programs with fast, short line segments and high frequency reports (5-20Hz). -void report_realtime_status (stream_write_ptr stream_write) +void report_realtime_status (stream_write_ptr stream_write, report_tracking_flags_t report) { static bool probing = false; uint_fast8_t idx; float print_position[N_AXIS], wco[N_AXIS], dist_remaining[N_AXIS]; - report_tracking_flags_t report = system_get_rt_report_flags(), delayed_report = {}; + report_tracking_flags_t delayed_report = {0}; probe_state_t probe_state = { .connected = On, .triggered = Off @@ -1234,7 +1262,7 @@ void report_realtime_status (stream_write_ptr stream_write) system_convert_array_steps_to_mpos(print_position, sys.position); if((report.distance_to_go = settings.status_report.distance_to_go)) { - // Calulate distance-to-go in current block (i.e., difference between target / end-of-block) and current position) + // Calculate distance-to-go in current block (i.e., difference between target / end-of-block) and current position) plan_block_t *cur_block = plan_get_current_block(); if((report.distance_to_go = !!cur_block)) { for(idx = 0; idx < N_AXIS; idx++) { @@ -1267,8 +1295,9 @@ void report_realtime_status (stream_write_ptr stream_write) if(settings.status_report.line_numbers) { // Report current line number plan_block_t *cur_block = plan_get_current_block(); - if (cur_block != NULL && cur_block->line_number > 0) - stream_write(appendbuf(2, "|Ln:", uitoa((uint32_t)cur_block->line_number))); + uint32_t line_number = cur_block ? cur_block->line_number : gc_state.line_number; + if(line_number) + stream_write(appendbuf(2, "|Ln:", uitoa(line_number))); } if(report.distance_to_go) { @@ -1311,8 +1340,13 @@ void report_realtime_status (stream_write_ptr stream_write) } #elif N_SPINDLE > 1 - if(report.spindle_id) - spindle_enumerate_spindles(report_spindle_num, &spindle_0->id); + if(report.spindle_id) { + spindle_r_t data = { + .spindle_id = spindle_0->id, + .stream_write = stream_write + }; + spindle_enumerate_spindles(report_spindle_num, &data); + } #endif if(settings.status_report.pin_state) { @@ -1402,11 +1436,15 @@ void report_realtime_status (stream_write_ptr stream_write) } stream_write("|WCO:"); stream_write(get_axis_values(wco)); +#ifdef ROTATION_ENABLE +// stream_write(":"); +// stream_write(ftoa(gc_state.modal.g5x_offset.data.rotation, 2)); +#endif } if(report.gwco) { stream_write("|WCS:"); - stream_write(gc_coord_system_to_str(gc_state.modal.coord_system.id)); + stream_write(gc_coord_system_to_str(gc_state.modal.g5x_offset.id)); } if(report.overrides) { @@ -1509,15 +1547,28 @@ void report_realtime_status (stream_write_ptr stream_write) static float feed_rate, spindle_rpm; static gc_modal_t last_state; static bool g92_active; +#if NGC_PARAMETERS_ENABLE + static bool g66_active; +#endif spindle_t *spindle = gc_spindle_get(0); - bool is_changed = feed_rate != gc_state.feed_rate || spindle_rpm != spindle->rpm || tool_id != gc_state.tool->tool_id; + bool is_changed = feed_rate != gc_state.feed_rate || + spindle_rpm != spindle->rpm || + tool_id != gc_state.tool->tool_id +#if NGC_PARAMETERS_ENABLE + || g66_active != !!gc_state.g66_args; +#else +; +#endif if(is_changed) { feed_rate = gc_state.feed_rate; tool_id = gc_state.tool->tool_id; spindle_rpm = spindle->rpm; - } else if ((is_changed = g92_active != is_g92_active())) +#if NGC_PARAMETERS_ENABLE + g66_active = !!gc_state.g66_args; +#endif + } else if((is_changed = g92_active != is_g92_active())) g92_active = !g92_active; else if(memcmp(&last_state, &gc_state.modal, sizeof(gc_modal_t))) { last_state = gc_state.modal; @@ -1533,10 +1584,12 @@ void report_realtime_status (stream_write_ptr stream_write) stream_write(">" ASCII_EOL); - system_add_rt_report(Report_ClearAll); + if(stream_write == hal.stream.write_all) { + system_add_rt_report(Report_ClearAll); - if(delayed_report.wco) - system_add_rt_report(Report_WCO); // Set to report on next request + if(delayed_report.wco) + system_add_rt_report(Report_WCO); // Set to report on next request + } } static void report_bitfield (const char *format, bool bitmap) @@ -2845,3 +2898,15 @@ void report_init_fns (void) if(grbl.on_report_handlers_init) grbl.on_report_handlers_init(); } + +report_tracking_flags_t report_get_rt_flags_all (void) +{ + report_tracking_flags_t report; + + report.value = (uint32_t)Report_All; + report.tool_offset = sys.report.tool_offset; + report.m66result = sys.var5399 > -2; + report.probe_id = !!hal.probe.select; + + return report; +} diff --git a/report.h b/report.h index 17dc4e9..043a9a3 100644 --- a/report.h +++ b/report.h @@ -3,21 +3,21 @@ Part of grblHAL - Copyright (c) 2018-2024 Terje Io + Copyright (c) 2018-2026 Terje Io Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _REPORT_H_ @@ -49,22 +49,22 @@ void report_info (void *message); // Message helper to be run as foreground task. void report_warning (void *message); -// Prints Grbl help. +// Prints grblHAL help. status_code_t report_help (char *args); void report_plugin (const char *name, const char *version); -// Prints Grbl settings +// Prints grblHAL settings void report_grbl_settings (bool all, void *data); -// Prints Grbl setting +// Prints grblHAL setting status_code_t report_grbl_setting (setting_id_t id, void *data); // Prints an echo of the pre-parsed line received right before execution. void report_echo_line_received (char *line); // Prints realtime status report. -void report_realtime_status (stream_write_ptr stream_write); +void report_realtime_status (stream_write_ptr stream_write, report_tracking_flags_t report); // Prints recorded probe position. void report_probe_parameters (void); @@ -82,11 +82,11 @@ status_code_t report_named_ngc_parameter (char *arg); #endif -// Prints Grbl NGC parameters (coordinate offsets, probe). +// Prints grblHAL NGC parameters (coordinate offsets, probe). void report_ngc_parameters (void); // Prints current g-code parser mode state. -void report_gcode_modes (void); +void report_gcode_modes (stream_write_ptr stream_write); // Prints startup line when requested and executed. void report_startup_line (uint8_t n, char *line); @@ -127,4 +127,6 @@ status_code_t report_time (void); // Prints current PID log. void report_pid_log (void); +report_tracking_flags_t report_get_rt_flags_all (void); + #endif diff --git a/settings.c b/settings.c index 0328f22..12e6874 100644 --- a/settings.c +++ b/settings.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2025 Terje Io + Copyright (c) 2017-2026 Terje Io Copyright (c) 2011-2015 Sungeun K. Jeon Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -146,6 +146,15 @@ PROGMEM const settings_t defaults = { .homing.cycle[0].mask = DEFAULT_HOMING_CYCLE_0, .homing.cycle[1].mask = DEFAULT_HOMING_CYCLE_1, .homing.cycle[2].mask = DEFAULT_HOMING_CYCLE_2, +#if N_AXIS > 3 + .homing.cycle[3].mask = DEFAULT_HOMING_CYCLE_3, +#endif +#if N_AXIS > 4 + .homing.cycle[4].mask = DEFAULT_HOMING_CYCLE_4, +#endif +#if N_AXIS > 5 + .homing.cycle[5].mask = DEFAULT_HOMING_CYCLE_5, +#endif .homing.dual_axis.fail_length_percent = DEFAULT_DUAL_AXIS_HOMING_FAIL_AXIS_LENGTH_PERCENT, .homing.dual_axis.fail_distance_min = DEFAULT_DUAL_AXIS_HOMING_FAIL_DISTANCE_MIN, .homing.dual_axis.fail_distance_max = DEFAULT_DUAL_AXIS_HOMING_FAIL_DISTANCE_MAX, @@ -277,7 +286,6 @@ PROGMEM const settings_t defaults = { #if ENABLE_BACKLASH_COMPENSATION .axis[A_AXIS].backlash = 0.0f, #endif - .homing.cycle[3].mask = DEFAULT_HOMING_CYCLE_3, #endif #ifdef B_AXIS @@ -292,7 +300,6 @@ PROGMEM const settings_t defaults = { #if ENABLE_BACKLASH_COMPENSATION .axis[B_AXIS].backlash = 0.0f, #endif - .homing.cycle[4].mask = DEFAULT_HOMING_CYCLE_4, #endif #ifdef C_AXIS @@ -307,9 +314,9 @@ PROGMEM const settings_t defaults = { #if ENABLE_BACKLASH_COMPENSATION .axis[C_AXIS].backlash = 0.0f, #endif - .homing.cycle[5].mask = DEFAULT_HOMING_CYCLE_5, #endif +#if !LATHE_UVW_OPTION #ifdef U_AXIS .axis[U_AXIS].steps_per_mm = DEFAULT_U_STEPS_PER_MM, .axis[U_AXIS].acceleration = (DEFAULT_U_ACCELERATION * 60.0f * 60.0f), @@ -338,6 +345,21 @@ PROGMEM const settings_t defaults = { #endif #endif +#ifdef W_AXIS + .axis[W_AXIS].steps_per_mm = DEFAULT_W_STEPS_PER_MM, + .axis[W_AXIS].acceleration = (DEFAULT_W_ACCELERATION * 60.0f * 60.0f), + .axis[W_AXIS].jerk = (DEFAULT_W_JERK * 60.0f * 60.0f * 60.0f), + .axis[W_AXIS].max_rate = DEFAULT_W_MAX_RATE, + .axis[W_AXIS].max_travel = (-DEFAULT_W_MAX_TRAVEL), + .axis[W_AXIS].dual_axis_offset = 0.0f, + .axis[W_AXIS].homing_feed_rate = DEFAULT_HOMING_FEED_RATE, + .axis[W_AXIS].homing_seek_rate = DEFAULT_HOMING_SEEK_RATE, +#if ENABLE_BACKLASH_COMPENSATION + .axis[W_AXIS].backlash = 0.0f, +#endif +#endif +#endif // !LATHE_UVW_OPTION + .tool_change.mode = (toolchange_mode_t)DEFAULT_TOOLCHANGE_MODE, .tool_change.probing_distance = DEFAULT_TOOLCHANGE_PROBING_DISTANCE, .tool_change.feed_rate = DEFAULT_TOOLCHANGE_FEED_RATE, @@ -363,7 +385,9 @@ PROGMEM const settings_t defaults = { .fs_options.hierarchical_listing = DEFAULT_FS_HIERACHICAL_LISTING, .modbus_baud = DEFAULT_MODBUS_STREAM_BAUD, - .modbus_stream_format.value = (DEFAULT_MODBUS_STREAM_PARITY << 4), + .modbus_stream_format.width = DEFAULT_MODBUS_STREAM_DATA_BITS, + .modbus_stream_format.stopbits = DEFAULT_MODBUS_STREAM_STOP_BITS, + .modbus_stream_format.parity = DEFAULT_MODBUS_STREAM_PARITY, .rgb_strip.length0 = DEFAULT_RGB_STRIP0_LENGTH, .rgb_strip.length1 = DEFAULT_RGB_STRIP1_LENGTH @@ -394,32 +418,23 @@ PROGMEM static const setting_group_detail_t setting_group_detail [] = { { Group_Axis, Group_XAxis, "X-axis", group_is_available }, { Group_Axis, Group_YAxis, "Y-axis", group_is_available }, { Group_Axis, Group_ZAxis, "Z-axis", group_is_available }, -#if !AXIS_REMAP_ABC2UVW - #ifdef A_AXIS - { Group_Axis, Group_AAxis, "A-axis", group_is_available }, - #endif - #ifdef B_AXIS - { Group_Axis, Group_BAxis, "B-axis", group_is_available }, - #endif - #ifdef C_AXIS - { Group_Axis, Group_CAxis, "C-axis", group_is_available }, - #endif - #ifdef U_AXIS - { Group_Axis, Group_UAxis, "U-axis", group_is_available }, - #endif - #ifdef V_AXIS - { Group_Axis, Group_VAxis, "V-axis", group_is_available } - #endif -#else - #ifdef A_AXIS - { Group_Axis, Group_AAxis, "U-axis", group_is_available }, - #endif - #ifdef B_AXIS - { Group_Axis, Group_BAxis, "V-axis", group_is_available }, - #endif - #ifdef C_AXIS - { Group_Axis, Group_CAxis, "W-axis", group_is_available }, +#ifdef A_AXIS + { Group_Axis, Group_Axis0 + A_AXIS, "A-axis", group_is_available }, +#endif +#ifdef B_AXIS + { Group_Axis, Group_Axis0 + B_AXIS, "B-axis", group_is_available }, +#endif +#ifdef C_AXIS + { Group_Axis, Group_Axis0 + C_AXIS, "C-axis", group_is_available }, +#endif +#ifdef U_AXIS + { Group_Axis, Group_Axis0 + U_AXIS, "U-axis", group_is_available }, #endif +#ifdef V_AXIS + { Group_Axis, Group_Axis0 + V_AXIS, "V-axis", group_is_available }, +#endif +#ifdef W_AXIS + { Group_Axis, Group_Axis0 + W_AXIS, "W-axis", group_is_available } #endif }; @@ -436,26 +451,16 @@ static char spindle_signals[] = "Spindle enable,Spindle direction,PWM"; static char coolant_signals[] = "Flood,Mist"; static char door_options[] = "Ignore when idle,Keep coolant state on door open"; static char ganged_axes[] = "X-Axis,Y-Axis,Z-Axis"; -#if !AXIS_REMAP_ABC2UVW - #if N_AXIS == 4 - static const char rotary_axes[] = "A-Axis"; - #elif N_AXIS == 5 - static const char rotary_axes[] = "A-Axis,B-Axis"; - #elif N_AXIS == 6 - static const char rotary_axes[] = "A-Axis,B-Axis,C-Axis"; - #elif N_AXIS == 7 - static const char rotary_axes[] = "A-Axis,B-Axis,C-Axis,U-Axis"; - #elif N_AXIS == 8 - static const char rotary_axes[] = "A-Axis,B-Axis,C-Axis,U-Axis,V-Axis"; - #endif -#else - #if N_AXIS == 4 - static const char rotary_axes[] = "U-Axis"; - #elif N_AXIS == 5 - static const char rotary_axes[] = "U-Axis,V-Axis"; - #elif N_AXIS == 6 - static const char rotary_axes[] = "U-Axis,V-Axis,W-Axis"; - #endif +#if N_AXIS == 4 +static char rotary_axes[] = "A-Axis"; +#elif N_AXIS == 5 +static char rotary_axes[] = "A-Axis,B-Axis"; +#elif N_AXIS == 6 +static char rotary_axes[] = "A-Axis,B-Axis,C-Axis"; +#elif N_AXIS == 7 +static char rotary_axes[] = "A-Axis,B-Axis,C-Axis,U-Axis"; +#elif N_AXIS == 8 +static char rotary_axes[] = "A-Axis,B-Axis,C-Axis,U-Axis,V-Axis"; #endif static on_file_demarcate_ptr on_file_demarcate; @@ -951,7 +956,7 @@ static status_code_t set_parking_enable (setting_id_t id, uint_fast16_t int_valu if(settings.parking.flags.deactivate_upon_init) settings.parking.flags.enable_override_control = On; - //setting_remove_elements(Setting_ProbePullUpDisable, mask); + //setting_remove_elements(Setting_ProbePullUpDisable, mask, true); return Status_OK; } @@ -1267,7 +1272,7 @@ setting_id_t settings_get_axis_base (setting_id_t id, uint_fast8_t *idx) return *idx < N_AXIS ? base : Setting_SettingsMax; } -static status_code_t set_float (setting_id_t setting, float value) +FLASHMEM static status_code_t set_float (setting_id_t setting, float value) { status_code_t status = Status_OK; @@ -1296,7 +1301,7 @@ static status_code_t set_float (setting_id_t setting, float value) return status; } -static status_code_t set_axis_setting (setting_id_t setting, float value) +FLASHMEM static status_code_t set_axis_setting (setting_id_t setting, float value) { uint_fast8_t idx; status_code_t status = Status_OK; @@ -1384,7 +1389,7 @@ static status_code_t set_axis_setting (setting_id_t setting, float value) return status; } -static float get_float (setting_id_t setting) +FLASHMEM static float get_float (setting_id_t setting) { float value = 0.0f; @@ -1482,7 +1487,7 @@ static float get_float (setting_id_t setting) return value; } -static uint32_t get_int (setting_id_t id) +FLASHMEM static uint32_t get_int (setting_id_t id) { uint32_t value = 0; @@ -1872,7 +1877,7 @@ static bool is_group_available (const setting_detail_t *setting, uint_fast16_t o return settings_is_group_available(setting->group); } -static bool is_setting_available (const setting_detail_t *setting, uint_fast16_t offset) +FLASHMEM static bool is_setting_available (const setting_detail_t *setting, uint_fast16_t offset) { bool available = false; @@ -1991,6 +1996,14 @@ static bool is_setting_available (const setting_detail_t *setting, uint_fast16_t available = hal.driver_cap.spindle_encoder && spindle_get_count() > 1; break; + case Setting_RGB_StripLengt0: + available = hal.rgb0.flags.is_strip; + break; + + case Setting_RGB_StripLengt1: + available = hal.rgb1.flags.is_strip; + break; + case Setting_FSOptions: available = hal.driver_cap.sd_card || hal.driver_cap.littlefs; break; @@ -2094,13 +2107,13 @@ PROGMEM static const setting_detail_t setting_detail[] = { { Setting_HomingCycle_1, Group_Homing, "Axes homing, first phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL }, { Setting_HomingCycle_2, Group_Homing, "Axes homing, second phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL }, { Setting_HomingCycle_3, Group_Homing, "Axes homing, third phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL }, -#ifdef A_AXIS +#if N_AXIS > 3 { Setting_HomingCycle_4, Group_Homing, "Axes homing, fourth phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL }, #endif -#ifdef B_AXIS +#if N_AXIS > 4 { Setting_HomingCycle_5, Group_Homing, "Axes homing, fifth phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL }, #endif -#ifdef C_AXIS +#if N_AXIS > 5 { Setting_HomingCycle_6, Group_Homing, "Axes homing, sixth phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL }, #endif { Setting_ParkingPulloutIncrement, Group_SafetyDoor, "Parking pull-out distance", "mm", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.pullout_increment, NULL, NULL }, @@ -2176,6 +2189,8 @@ PROGMEM static const setting_detail_t setting_detail[] = { { Setting_OffsetLock, Group_General, "Lock coordinate systems", NULL, Format_Bitfield, "G59.1,G59.2,G59.3", NULL, NULL, Setting_IsExtended, &settings.offset_lock.mask, NULL, NULL }, #endif { Setting_EncoderSpindle, Group_Spindle, "Encoder spindle", NULL, Format_RadioButtons, spindle_types, NULL, NULL, Setting_IsExtendedFn, set_encoder_spindle, get_int, is_setting_available }, + { Setting_RGB_StripLengt0, Group_AuxPorts, "LED strip 1 length", NULL, Format_Int8, "##0", NULL, "255", Setting_NonCore, &settings.rgb_strip.length0, NULL, is_setting_available }, + { Setting_RGB_StripLengt1, Group_AuxPorts, "LED strip 2 length", NULL, Format_Int8, "##0", NULL, "255", Setting_NonCore, &settings.rgb_strip.length1, NULL, is_setting_available }, #if N_AXIS > 3 { Setting_RotaryWrap, Group_Stepper, "Fast rotary go to G28", NULL, Format_Bitfield, rotary_axes, NULL, NULL, Setting_IsExtendedFn, set_rotary_wrap_axes, get_int, NULL }, #endif @@ -2269,13 +2284,13 @@ PROGMEM static const setting_descr_t setting_descr[] = { { Setting_HomingCycle_1, "Axes to home in first phase." }, { Setting_HomingCycle_2, "Axes to home in second phase." }, { Setting_HomingCycle_3, "Axes to home in third phase." }, -#ifdef A_AXIS +#if N_AXIS > 3 { Setting_HomingCycle_4, "Axes to home in fourth phase." }, #endif -#ifdef B_AXIS +#if N_AXIS > 4 { Setting_HomingCycle_5, "Axes to home in fifth phase." }, #endif -#ifdef C_AXIS +#if N_AXIS > 5 { Setting_HomingCycle_6, "Axes to home in sixth phase." }, #endif { Setting_JogStepSpeed, "Step jogging speed in millimeters per minute." }, @@ -2332,8 +2347,8 @@ PROGMEM static const setting_descr_t setting_descr[] = { { Setting_AxisHomingFeedRate, "Feed rate to slowly engage limit switch to determine its location accurately." }, { Setting_AxisHomingSeekRate, "Seek rate to quickly find the limit switch before the slower locating phase." }, { Setting_SpindleAtSpeedTolerance, "Spindle at speed tolerance as percentage deviation from programmed speed, set to 0 to disable.\\n" - "If not within tolerance after timeout set by spindle on delay ($394) alarm 14 is raised.\\n" - "NOTE: if the spindle on delay is set to 0 the timeout defaults to one minute." + "If not within tolerance after timeout set by spindle delays ($392, $394 or $539) alarm 14 is raised.\\n" + "NOTE: if the delay is set to 0 the timeout defaults to one minute." }, { Setting_ToolChangeMode, "Normal: allows jogging for manual touch off. Set new position manually.\\n\\n" "Manual touch off: rapids to tool change position, use jogging or $TPW for touch off.\\n\\n" @@ -2382,6 +2397,8 @@ PROGMEM static const setting_descr_t setting_descr[] = { "If spindle supports \"at speed\" functionality it is the time to wait before alarm 14 is raised." }, { Setting_EncoderSpindle, "Specifies which spindle has the encoder attached." }, + { Setting_RGB_StripLengt0, "Number of LEDS in strip 1." }, + { Setting_RGB_StripLengt1, "Number of LEDS in strip 2." }, #if N_AXIS > 3 { Setting_RotaryWrap, "Perform fast move to angle stored in G28 position.\\n" "Use:\\n" @@ -2473,7 +2490,7 @@ bool settings_read_startup_line (uint8_t idx, char *line) } // Write selected coordinate data to persistent storage. -void settings_write_coord_data (coord_system_id_t id, const float (*coord_data)[N_AXIS]) +void settings_write_coord_data (coord_system_id_t id, coord_system_data_t *data) { assert(id <= N_CoordinateSystems); @@ -2482,23 +2499,24 @@ void settings_write_coord_data (coord_system_id_t id, const float (*coord_data)[ #endif if(grbl.on_wco_saved) - grbl.on_wco_saved(id, (coord_data_t *)coord_data); + grbl.on_wco_saved(id, data); if(hal.nvs.type != NVS_None) - hal.nvs.memcpy_to_nvs(NVS_ADDR_PARAMETERS + id * (sizeof(coord_data_t) + NVS_CRC_BYTES), (uint8_t *)coord_data, sizeof(coord_data_t), true); + hal.nvs.memcpy_to_nvs(NVS_ADDR_PARAMETERS + id * (sizeof(coord_system_data_t) + NVS_CRC_BYTES), (uint8_t *)data, sizeof(coord_system_data_t), true); } // Read selected coordinate data from persistent storage. -bool settings_read_coord_data (coord_system_id_t id, const float (*coord_data)[N_AXIS]) +bool settings_read_coord_data (coord_system_id_t id, coord_system_data_t *data) { assert(id <= N_CoordinateSystems); - if (!(hal.nvs.type != NVS_None && hal.nvs.memcpy_from_nvs((uint8_t *)coord_data, NVS_ADDR_PARAMETERS + id * (sizeof(coord_data_t) + NVS_CRC_BYTES), sizeof(coord_data_t), true) == NVS_TransferResult_OK)) { - // Reset with default zero vector - memcpy((float *)coord_data, null_vector.values, sizeof(coord_data_t)); - settings_write_coord_data(id, coord_data); + if(!(hal.nvs.type != NVS_None && hal.nvs.memcpy_from_nvs((uint8_t *)data, NVS_ADDR_PARAMETERS + id * (sizeof(coord_system_data_t) + NVS_CRC_BYTES), sizeof(coord_system_data_t), true) == NVS_TransferResult_OK)) { + // Reset with zero vector + memset(data, 0, sizeof(coord_system_data_t)); + settings_write_coord_data(id, data); return false; } + return true; } @@ -2718,14 +2736,13 @@ void settings_restore (settings_restore_t restore) } if(restore.parameters) { - float coord_data[N_AXIS]; - memset(coord_data, 0, sizeof(coord_data)); -#if COMPATIBILITY_LEVEL <= 1 + coord_system_data_t coord_data = {0}; for(idx = 0; idx <= N_WorkCoordinateSystems; idx++) { +#if COMPATIBILITY_LEVEL <= 1 if(idx < CoordinateSystem_G59_1 || idx > CoordinateSystem_G59_3 || bit_isfalse(settings.offset_lock.mask, bit(idx - CoordinateSystem_G59_1))) +#endif settings_write_coord_data((coord_system_id_t)idx, &coord_data); } -#endif settings_write_coord_data(CoordinateSystem_G92, &coord_data); // Clear G92 offsets #if N_TOOLS @@ -3100,7 +3117,7 @@ static void setting_remove_element (setting_id_t id, uint_fast8_t pos) // Flag setting elements for bitfields as N/A according to a mask // Note: setting format string has to reside in RAM. -void setting_remove_elements (setting_id_t id, uint32_t mask) +void setting_remove_elements (setting_id_t id, uint32_t mask, bool trim) { const setting_detail_t *setting; @@ -3116,7 +3133,7 @@ void setting_remove_elements (setting_id_t id, uint32_t mask) } // Strip trailing N/A's - while((s = strrchr(format, ','))) { + if(trim) while((s = strrchr(format, ','))) { if(strncmp(s, ",N/A", 4)) break; *s = '\0'; @@ -3250,7 +3267,7 @@ static bool settings_changed_spindle (void) } // A helper method to set settings from command line -status_code_t settings_store_setting (setting_id_t id, char *svalue) +FLASHMEM status_code_t settings_store_setting (setting_id_t id, char *svalue) { uint_fast8_t set_idx = 0; uint32_t int_value = 0; @@ -3483,27 +3500,30 @@ void settings_init (void) spindle_state.ccw = spindle_cap.direction; spindle_state.pwm = spindle_cap.pwm_invert; - setting_remove_elements(Setting_SpindleInvertMask, spindle_state.mask); + setting_remove_elements(Setting_SpindleInvertMask, spindle_state.mask, true); } - setting_remove_elements(Setting_ControlInvertMask, hal.signals_cap.mask & ~limits_override.mask); + setting_remove_elements(Setting_ControlInvertMask, hal.signals_cap.mask & ~limits_override.mask, true); if(hal.stepper.get_ganged) - setting_remove_elements(Setting_GangedDirInvertMask, hal.stepper.get_ganged(false).mask); + setting_remove_elements(Setting_GangedDirInvertMask, hal.stepper.get_ganged(false).mask, true); - setting_remove_elements(Setting_CoolantInvertMask, hal.coolant_cap.mask); + setting_remove_elements(Setting_CoolantInvertMask, hal.coolant_cap.mask, true); #if COMPATIBILITY_LEVEL <= 1 if(hal.homing.get_state == NULL) { homing_settings_flags_t homing; homing.value = (uint16_t)-1; homing.use_limit_switches = Off; - setting_remove_elements(Setting_HomingEnable, homing.value); + setting_remove_elements(Setting_HomingEnable, homing.value, true); } #endif -#if ENABLE_JERK_ACCELERATION +#if N_AXIS > 3 || ENABLE_JERK_ACCELERATION uint_fast8_t idx = N_AXIS; +#endif + +#if ENABLE_JERK_ACCELERATION do { if(settings.axis[--idx].jerk == 0.0f) settings.axis[idx].jerk = settings.axis[idx].acceleration * 60.0f * 10.0f; @@ -3520,10 +3540,14 @@ void settings_init (void) } while((details = details->next)); uint32_t mask = 0b001 | (hal.driver_cap.toolsetter << 1) | (hal.driver_cap.probe2 << 2); - setting_remove_elements(Setting_InvertProbePin, mask); - setting_remove_elements(Setting_ProbePullUpDisable, mask); + setting_remove_elements(Setting_InvertProbePin, mask, true); + setting_remove_elements(Setting_ProbePullUpDisable, mask, true); #ifndef NO_SAFETY_DOOR_SUPPORT - setting_remove_elements(Setting_DoorOptions, ((!settings.parking.flags.enabled || hal.signals_cap.safety_door_ajar) << 1) | hal.signals_cap.safety_door_ajar); + setting_remove_elements(Setting_DoorOptions, ((!settings.parking.flags.enabled || hal.signals_cap.safety_door_ajar) << 1) | hal.signals_cap.safety_door_ajar, true); +#endif +#if N_AXIS > 3 + for(idx = 3; idx < N_AXIS; idx++) + *(rotary_axes + (idx - 3) * 7) = *axis_letter[idx]; #endif mask = 0b00011 | (hal.probe.select ? ((hal.driver_cap.toolsetter << 3) | (hal.driver_cap.probe2 << 4)) : 0); @@ -3535,7 +3559,7 @@ void settings_init (void) #else settings.probe.enable_protection = Off; #endif - setting_remove_elements(Setting_ProbingFlags, mask); + setting_remove_elements(Setting_ProbingFlags, mask, true); if(!settings.flags.settings_downgrade && settings.version.build != (GRBL_BUILD - 20000000UL)) { diff --git a/settings.h b/settings.h index cfe2a85..6f5e6e2 100644 --- a/settings.h +++ b/settings.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2025 Terje Io + Copyright (c) 2017-2026 Terje Io Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -969,21 +969,12 @@ typedef enum { Group_XAxis = Group_Axis0, //!< 44 Group_YAxis, //!< 45 Group_ZAxis, //!< 46 -#ifdef A_AXIS Group_AAxis, //!< 47 -#endif -#ifdef B_AXIS Group_BAxis, //!< 48 -#endif -#ifdef C_AXIS Group_CAxis, //!< 49 -#endif -#ifdef U_AXIS Group_UAxis, //!< 50 -#endif -#ifdef V_AXIS Group_VAxis, //!< 51 -#endif + Group_WAxis, //!< 52 Group_Unknown = 99, //!< 99 Group_All = Group_Root //!< 0 } setting_group_t; @@ -1140,10 +1131,10 @@ void settings_write_build_info(char *line); bool settings_read_build_info(char *line); // Writes selected coordinate data to persistent storage -void settings_write_coord_data(coord_system_id_t id, const float (*coord_data)[N_AXIS]); +void settings_write_coord_data(coord_system_id_t id, coord_system_data_t *data); // Reads selected coordinate data from persistent storage -bool settings_read_coord_data(coord_system_id_t id, const float (*coord_data)[N_AXIS]); +bool settings_read_coord_data(coord_system_id_t id, coord_system_data_t *data); // Temporarily override acceleration, if 0 restore to configured setting value bool settings_override_acceleration (uint8_t axis, float acceleration); @@ -1168,7 +1159,7 @@ float setting_get_float_value (const setting_detail_t *setting, uint_fast16_t of setting_id_t settings_get_axis_base (setting_id_t id, uint_fast8_t *idx); bool setting_is_list (const setting_detail_t *setting); bool setting_is_integer (const setting_detail_t *setting); -void setting_remove_elements (setting_id_t id, uint32_t mask); +void setting_remove_elements (setting_id_t id, uint32_t mask, bool trim); bool settings_add_spindle_type (const char *type); limit_signals_t settings_get_homing_source (void); diff --git a/sleep.c b/sleep.c index c35e125..51dd184 100644 --- a/sleep.c +++ b/sleep.c @@ -53,7 +53,7 @@ static void sleep_execute (void) } while(slumber); // If reached, sleep counter has expired. Execute sleep procedures. - // Notify user that Grbl has timed out and will be parking. + // Notify user that grblHAL has timed out and will be parking. // To exit sleep, resume or reset. Either way, the job will not be recoverable. system_set_exec_state_flag(EXEC_SLEEP); } diff --git a/sleep.h b/sleep.h index 2cfca6b..a2c943f 100644 --- a/sleep.h +++ b/sleep.h @@ -5,18 +5,18 @@ Copyright (c) 2016 Sungeun K. Jeon - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _SLEEP_H_ diff --git a/spindle_control.c b/spindle_control.c index c178f68..4d4afce 100644 --- a/spindle_control.c +++ b/spindle_control.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2025 Terje Io + Copyright (c) 2017-2026 Terje Io Copyright (c) 2012-2015 Sungeun K. Jeon Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -1261,7 +1261,7 @@ void spindle1_settings_register (spindle_cap_t cap, spindle1_settings_changed_pt spindle_state.ccw = cap.direction; spindle_state.pwm = cap.pwm_invert; - setting_remove_elements(Setting_SpindleInvertMask1, spindle_state.mask); + setting_remove_elements(Setting_SpindleInvertMask1, spindle_state.mask, true); } #endif // N_SPINDLE > 1 diff --git a/state_machine.h b/state_machine.h index c57c675..a782fd2 100644 --- a/state_machine.h +++ b/state_machine.h @@ -7,18 +7,18 @@ Copyright (c) 2018-2023 Terje Io - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #ifndef _STATE_MACHINE_H_ diff --git a/stepdir_map.h b/stepdir_map.h index 36a8ec2..e6f1d2f 100644 --- a/stepdir_map.h +++ b/stepdir_map.h @@ -5,24 +5,24 @@ May be used by driver code if step and/or dir pins are located to the same port. - NOT referenced in the core grbl code + NOT referenced in the core grblHAL code Part of grblHAL - Copyright (c) 2021-2022 Terje Io + Copyright (c) 2021-2025 Terje Io - Grbl is free software: you can redistribute it and/or modify + grblHAL 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, + grblHAL 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 + 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 . + along with grblHAL. If not, see . */ #if STEP_OUTMODE == GPIO_MAP @@ -37,262 +37,262 @@ static const uint32_t c_step_outmap[] = { Z_STEP_BIT | Y_STEP_BIT, Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, #if N_AXIS > 3 - A_STEP_BIT, - A_STEP_BIT | X_STEP_BIT, - A_STEP_BIT | Y_STEP_BIT, - A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - A_STEP_BIT | Z_STEP_BIT, - A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M3_STEP_BIT, + M3_STEP_BIT | X_STEP_BIT, + M3_STEP_BIT | Y_STEP_BIT, + M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M3_STEP_BIT | Z_STEP_BIT, + M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, #endif #if N_AXIS > 4 - B_STEP_BIT, - B_STEP_BIT | X_STEP_BIT, - B_STEP_BIT | Y_STEP_BIT, - B_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - B_STEP_BIT | Z_STEP_BIT, - B_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - B_STEP_BIT | A_STEP_BIT, - B_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M4_STEP_BIT, + M4_STEP_BIT | X_STEP_BIT, + M4_STEP_BIT | Y_STEP_BIT, + M4_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M4_STEP_BIT | Z_STEP_BIT, + M4_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M4_STEP_BIT | M3_STEP_BIT, + M4_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, #endif #if N_AXIS > 5 - C_STEP_BIT, - C_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | Y_STEP_BIT, - C_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | Z_STEP_BIT, - C_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - C_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | A_STEP_BIT, - C_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - C_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | B_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | Y_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | A_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT, + M5_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | Y_STEP_BIT, + M5_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | Z_STEP_BIT, + M5_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M5_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M3_STEP_BIT, + M5_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M5_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, #endif #if N_AXIS > 6 - U_STEP_BIT, - U_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | Z_STEP_BIT, - U_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | A_STEP_BIT, - U_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - U_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | B_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | Z_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | A_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | Z_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | A_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT, + M6_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | Z_STEP_BIT, + M6_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M3_STEP_BIT, + M6_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M6_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, #endif #if N_AXIS > 7 - V_STEP_BIT, - V_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | A_STEP_BIT, - V_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | B_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | A_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | A_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | A_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | A_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | A_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, - V_STEP_BIT | U_STEP_BIT | C_STEP_BIT | B_STEP_BIT | A_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT, + M7_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M3_STEP_BIT, + M7_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M3_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | X_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT, + M7_STEP_BIT | M6_STEP_BIT | M5_STEP_BIT | M4_STEP_BIT | M3_STEP_BIT | Z_STEP_BIT | Y_STEP_BIT | X_STEP_BIT, #endif }; @@ -312,262 +312,262 @@ static const uint32_t c_dir_outmap[] = { Z_DIRECTION_BIT | Y_DIRECTION_BIT, Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, #if N_AXIS > 3 - A_DIRECTION_BIT, - A_DIRECTION_BIT | X_DIRECTION_BIT, - A_DIRECTION_BIT | Y_DIRECTION_BIT, - A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - A_DIRECTION_BIT | Z_DIRECTION_BIT, - A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M3_DIRECTION_BIT, + M3_DIRECTION_BIT | X_DIRECTION_BIT, + M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, #endif #if N_AXIS > 4 - B_DIRECTION_BIT, - B_DIRECTION_BIT | X_DIRECTION_BIT, - B_DIRECTION_BIT | Y_DIRECTION_BIT, - B_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - B_DIRECTION_BIT | Z_DIRECTION_BIT, - B_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - B_DIRECTION_BIT | A_DIRECTION_BIT, - B_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M4_DIRECTION_BIT, + M4_DIRECTION_BIT | X_DIRECTION_BIT, + M4_DIRECTION_BIT | Y_DIRECTION_BIT, + M4_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M4_DIRECTION_BIT | Z_DIRECTION_BIT, + M4_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M4_DIRECTION_BIT | M3_DIRECTION_BIT, + M4_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, #endif #if N_AXIS > 5 - C_DIRECTION_BIT, - C_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | Y_DIRECTION_BIT, - C_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | Z_DIRECTION_BIT, - C_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - C_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | A_DIRECTION_BIT, - C_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - C_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT, + M5_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | Y_DIRECTION_BIT, + M5_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | Z_DIRECTION_BIT, + M5_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M5_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M3_DIRECTION_BIT, + M5_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M5_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, #endif #if N_AXIS > 6 - U_DIRECTION_BIT, - U_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | Z_DIRECTION_BIT, - U_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | A_DIRECTION_BIT, - U_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - U_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT, + M6_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | Z_DIRECTION_BIT, + M6_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M3_DIRECTION_BIT, + M6_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M6_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, #endif #if N_AXIS > 7 - V_DIRECTION_BIT, - V_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | A_DIRECTION_BIT, - V_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | A_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, - V_DIRECTION_BIT | U_DIRECTION_BIT | C_DIRECTION_BIT | B_DIRECTION_BIT | A_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT, + M7_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M3_DIRECTION_BIT, + M7_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M3_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | X_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT, + M7_DIRECTION_BIT | M6_DIRECTION_BIT | M5_DIRECTION_BIT | M4_DIRECTION_BIT | M3_DIRECTION_BIT | Z_DIRECTION_BIT | Y_DIRECTION_BIT | X_DIRECTION_BIT, #endif }; diff --git a/stepper.c b/stepper.c index c21eb57..ebd4831 100644 --- a/stepper.c +++ b/stepper.c @@ -89,11 +89,6 @@ static float cycles_per_min; // Step segment ring buffer pointers static volatile segment_t *segment_buffer_tail, *segment_buffer_head; -#if ENABLE_JERK_ACCELERATION -// Static storage for acceleration value of last computed segment. -static float last_segment_accel = 0.0f; -#endif - // Pointers for the step segment being prepped from the planner buffer. Accessed only by the // main program. Pointers may be planning segments or planner blocks ahead of what being executed. static plan_block_t *pl_block; // Pointer to the planner block being prepped @@ -102,9 +97,13 @@ static st_block_t st_hold_block; // Copy of stepper block data for block put o // Segment preparation data struct. Contains all the necessary information to compute new segments // based on the current executing planner block. -typedef struct { +DCRAM static struct { prep_flags_t recalculate; - + ramp_type_t ramp_type; // Current segment ramp state +#if ENABLE_JERK_ACCELERATION + bool jerk; + float last_accel; // Acceleration of last computed segment. +#endif float dt_remainder; uint32_t steps_remaining; float steps_per_mm; @@ -115,7 +114,6 @@ typedef struct { float last_steps_per_mm; float last_dt_remainder; - ramp_type_t ramp_type; // Current segment ramp state float mm_complete; // End of velocity profile from end of current planner block in (mm). // NOTE: This value must coincide with a step(no mantissa) when converted. float current_speed; // Current speed at the end of the segment buffer (mm/min) @@ -130,11 +128,56 @@ typedef struct { float target_feed; // float inv_feedrate; // Used by PWM laser mode to speed up segment calculations. float current_spindle_rpm; -} st_prep_t; +} prep; //! \endcond -DCRAM static st_prep_t prep; +//DCRAM static st_prep_t prep; + +#ifdef JERK_LOG + +jlog_t jlog; + +static status_code_t jlog_out (sys_state_t state, char *args) +{ + uint32_t idx; + + hal.stream.write("[JLOG:"); + hal.stream.write(trim_float(ftoa(jlog.max_accel, 6))); + hal.stream.write(","); + hal.stream.write(trim_float(ftoa(jlog.accel, 6))); + hal.stream.write(","); + hal.stream.write(trim_float(ftoa(jlog.jerk, 6))); + hal.stream.write("]" ASCII_EOL); + + for(idx = 0; idx < jlog.idx; idx++) { + hal.stream.write("["); + hal.stream.write(trim_float(ftoa(jlog.data[idx].s0, 6))); + hal.stream.write(","); + hal.stream.write(trim_float(ftoa(jlog.data[idx].s, 6))); + hal.stream.write(","); + hal.stream.write(trim_float(ftoa(jlog.data[idx].v0, 6))); + hal.stream.write(","); + hal.stream.write(trim_float(ftoa(jlog.data[idx].v, 6))); + hal.stream.write(","); + hal.stream.write(trim_float(ftoa(jlog.data[idx].a0, 6))); + hal.stream.write(","); + hal.stream.write(trim_float(ftoa(jlog.data[idx].da, 6))); + hal.stream.write(","); + hal.stream.write(trim_float(ftoa(jlog.data[idx].t, 6))); + hal.stream.write(","); + hal.stream.write(trim_float(ftoa(jlog.data[idx].v, 6))); + hal.stream.write(","); + hal.stream.write(trim_float(ftoa(jlog.data[idx].mm_remaining, 6))); + hal.stream.write(","); + hal.stream.write(trim_float(ftoa(jlog.data[idx].time_var, 6))); + hal.stream.write("]" ASCII_EOL); + } + + return Status_OK; +} + +#endif extern void gc_output_message (char *message); @@ -497,6 +540,9 @@ ISR_CODE void ISR_FUNC(stepper_driver_interrupt_handler)(void) #endif #ifdef V_AXIS = st.counter.v + #endif + #ifdef W_AXIS + = st.counter.w #endif = st.step_event_count >> 1; @@ -557,8 +603,8 @@ ISR_CODE void ISR_FUNC(stepper_driver_interrupt_handler)(void) // Execute step displacement profile by Bresenham line algorithm - st.counter.x += st.steps.value[X_AXIS]; - if (st.counter.x > st.step_event_count) { + st.counter.x += st.steps.x; + if(st.counter.x > st.step_event_count) { step_out.x = On; st.counter.x -= st.step_event_count; #if ENABLE_BACKLASH_COMPENSATION @@ -567,8 +613,8 @@ ISR_CODE void ISR_FUNC(stepper_driver_interrupt_handler)(void) sys.position[X_AXIS] = sys.position[X_AXIS] + (st.dir_out.x ? -1 : 1); } - st.counter.y += st.steps.value[Y_AXIS]; - if (st.counter.y > st.step_event_count) { + st.counter.y += st.steps.y; + if(st.counter.y > st.step_event_count) { step_out.y = On; st.counter.y -= st.step_event_count; #if ENABLE_BACKLASH_COMPENSATION @@ -578,76 +624,88 @@ ISR_CODE void ISR_FUNC(stepper_driver_interrupt_handler)(void) } if(st.steps.value[Z_AXIS]) { - st.counter.z += st.steps.value[Z_AXIS]; - if (st.counter.z > st.step_event_count) { - step_out.z = On; - st.counter.z -= st.step_event_count; + st.counter.z += st.steps.z; + if(st.counter.z > st.step_event_count) { + step_out.z = On; + st.counter.z -= st.step_event_count; #if ENABLE_BACKLASH_COMPENSATION - if(!backlash_motion) + if(!backlash_motion) #endif - sys.position[Z_AXIS] = sys.position[Z_AXIS] + (st.dir_out.z ? -1 : 1); - } + sys.position[Z_AXIS] = sys.position[Z_AXIS] + (st.dir_out.z ? -1 : 1); + } } - #ifdef A_AXIS - st.counter.a += st.steps.value[A_AXIS]; - if (st.counter.a > st.step_event_count) { +#ifdef A_AXIS + st.counter.a += st.steps.a; + if(st.counter.a > st.step_event_count) { step_out.a = On; st.counter.a -= st.step_event_count; -#if ENABLE_BACKLASH_COMPENSATION + #if ENABLE_BACKLASH_COMPENSATION if(!backlash_motion) -#endif - sys.position[A_AXIS] = sys.position[A_AXIS] + (st.dir_out.a ? -1 : 1); - } #endif + sys.position[A_AXIS] = sys.position[A_AXIS] + (st.dir_out.a ? -1 : 1); + } +#endif - #ifdef B_AXIS - st.counter.b += st.steps.value[B_AXIS]; - if (st.counter.b > st.step_event_count) { +#ifdef B_AXIS + st.counter.b += st.steps.b; + if(st.counter.b > st.step_event_count) { step_out.b = On; st.counter.b -= st.step_event_count; -#if ENABLE_BACKLASH_COMPENSATION + #if ENABLE_BACKLASH_COMPENSATION if(!backlash_motion) -#endif - sys.position[B_AXIS] = sys.position[B_AXIS] + (st.dir_out.b ? -1 : 1); - } #endif + sys.position[B_AXIS] = sys.position[B_AXIS] + (st.dir_out.b ? -1 : 1); + } +#endif - #ifdef C_AXIS - st.counter.c += st.steps.value[C_AXIS]; - if (st.counter.c > st.step_event_count) { +#ifdef C_AXIS + st.counter.c += st.steps.c; + if(st.counter.c > st.step_event_count) { step_out.c = On; st.counter.c -= st.step_event_count; -#if ENABLE_BACKLASH_COMPENSATION + #if ENABLE_BACKLASH_COMPENSATION if(!backlash_motion) -#endif - sys.position[C_AXIS] = sys.position[C_AXIS] + (st.dir_out.c ? -1 : 1); - } #endif + sys.position[C_AXIS] = sys.position[C_AXIS] + (st.dir_out.c ? -1 : 1); + } +#endif - #ifdef U_AXIS - st.counter.u += st.steps.value[U_AXIS]; - if (st.counter.u > st.step_event_count) { +#ifdef U_AXIS + st.counter.u += st.steps.u; + if(st.counter.u > st.step_event_count) { step_out.u = On; st.counter.u -= st.step_event_count; #if ENABLE_BACKLASH_COMPENSATION if(!backlash_motion) #endif - sys.position[U_AXIS] = sys.position[U_AXIS] + (st.dir_out.u ? -1 : 1); + sys.position[U_AXIS] = sys.position[U_AXIS] + (st.dir_out.u ? -1 : 1); } #endif - #ifdef V_AXIS - st.counter.v += st.steps.value[V_AXIS]; - if (st.counter.v > st.step_event_count) { +#ifdef V_AXIS + st.counter.v += st.steps.v; + if(st.counter.v > st.step_event_count) { step_out.v = On; st.counter.v -= st.step_event_count; -#if ENABLE_BACKLASH_COMPENSATION + #if ENABLE_BACKLASH_COMPENSATION if(!backlash_motion) -#endif - sys.position[V_AXIS] = sys.position[V_AXIS] + (st.dir_out.v ? -1 : 1); - } #endif + sys.position[V_AXIS] = sys.position[V_AXIS] + (st.dir_out.v ? -1 : 1); + } +#endif + +#ifdef W_AXIS + st.counter.w += st.steps.w; + if (st.counter.w > st.step_event_count) { + step_out.w = On; + st.counter.w -= st.step_event_count; + #if ENABLE_BACKLASH_COMPENSATION + if(!backlash_motion) + #endif + sys.position[W_AXIS] = sys.position[W_AXIS] + (st.dir_out.w ? -1 : 1); + } +#endif st.step_out.bits = step_out.bits; @@ -699,7 +757,7 @@ void st_reset (void) pl_block = NULL; // Planner block pointer used by segment buffer segment_buffer_tail = segment_buffer_head = &segment_buffer[0]; // empty = tail - memset(&prep, 0, sizeof(st_prep_t)); + memset(&prep, 0, sizeof(prep)); memset(&st, 0, sizeof(stepper_t)); #if ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING @@ -712,6 +770,27 @@ void st_reset (void) #endif cycles_per_min = (float)hal.f_step_timer * 60.0f; + +#ifdef JERK_LOG + static bool ok = false; + + memset(&jlog, 0, sizeof(jlog_t)); + + if(!ok) { + ok = true; + + static const sys_command_t jerk_command_list[] = { + {"JLOG", jlog_out, { .noargs = On }, { .str = "output jerk log" } }, + }; + + static sys_commands_t jerk_commands = { + .n_commands = sizeof(jerk_command_list) / sizeof(sys_command_t), + .commands = jerk_command_list + }; + + system_register_commands(&jerk_commands); + } +#endif } // Called by spindle_set_state() to inform about RPM changes. @@ -838,6 +917,14 @@ void st_prep_buffer (void) st_prep_block = st_prep_block->next; +#ifdef JERK_LOG + memset(&jlog, 0, sizeof(jlog_t)); + + jlog.accel = pl_block->acceleration; + jlog.max_accel = pl_block->max_acceleration; + jlog.jerk = pl_block->jerk; +#endif + uint_fast8_t idx = N_AXIS; #if ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING // With AMASS enabled, simply bit-shift multiply all Bresenham data by the max AMASS @@ -874,6 +961,9 @@ void st_prep_buffer (void) prep.steps_remaining = pl_block->step_event_count; prep.req_mm_increment = REQ_MM_INCREMENT_SCALAR / prep.steps_per_mm; prep.dt_remainder = prep.target_position = 0.0f; // Reset for new segment block +#if ENABLE_JERK_ACCELERATION + prep.jerk = pl_block->condition.jerk; +#endif #ifdef KINEMATICS_API prep.rate_multiplier = pl_block->rate_multiplier; #endif @@ -1026,10 +1116,6 @@ void st_prep_buffer (void) float speed_var; // Speed worker variable float mm_remaining = pl_block->millimeters; // New segment distance from end of block. float minimum_mm = mm_remaining - prep.req_mm_increment; // Guarantee at least one step. -#if ENABLE_JERK_ACCELERATION - float time_to_jerk; // time needed for jerk ramp - float jerk_rampdown; // calculated startpoint of jerk rampdown -#endif if (minimum_mm < 0.0f) minimum_mm = 0.0f; @@ -1050,26 +1136,48 @@ void st_prep_buffer (void) mm_remaining -= time_var * (prep.current_speed - 0.5f * speed_var); prep.current_speed -= speed_var; } +#if ENABLE_JERK_ACCELERATION + prep.last_accel = 0.0f; // reset acceleration variable to 0 for next accel ramp +#endif break; case Ramp_Accel: // NOTE: Acceleration ramp only computes during first do-while loop. #if ENABLE_JERK_ACCELERATION - time_to_jerk = last_segment_accel / pl_block->jerk; - jerk_rampdown =time_to_jerk * (prep.current_speed + (0.5f * last_segment_accel * time_to_jerk) + (pl_block->jerk * time_to_jerk * time_to_jerk) / 6.0f); //Distance to 0 acceleration at speed (mm == V(0)*T + 1/2 A0*T^2 + 1/6 J*T^3) - if ((mm_remaining - prep.accelerate_until) > jerk_rampdown) { - //+1.0f to avoid divide by 0 speed, minor effect on jerk ramp - // Check if we are on ramp up or ramp down. Ramp down if distance to end of acceleration is less than distance needed to reach 0 acceleration. - // Then limit acceleration change by jerk up to max acceleration and update for next segment. - // Minimum acceleration jerk per time_var to ensure acceleration completes. Acceleration change at end of ramp is in acceptable jerk range. - last_segment_accel = min(last_segment_accel + pl_block->jerk * time_var, pl_block->max_acceleration); - } else { - last_segment_accel = max(last_segment_accel - pl_block->jerk * time_var, pl_block->jerk * time_var); - } - speed_var = last_segment_accel * time_var; -#else - speed_var = pl_block->acceleration * time_var; + if(prep.jerk) { + float accel_var = pl_block->jerk * time_var; // Delta acceleration + float time_to_jerk = prep.last_accel / pl_block->jerk; + //Distance to 0 acceleration at speed (mm == V(0)*T + 1/2 A0*T^2 + 1/6 J*T^3) + float jerk_rampdown = time_to_jerk * (prep.current_speed + + (0.5f * prep.last_accel * time_to_jerk) + + pl_block->jerk * time_to_jerk * time_to_jerk * (1.0f / 6.0f)); +#ifdef JERK_LOG + jlog.data[jlog.idx].s0 = mm_remaining - prep.accelerate_until; + jlog.data[jlog.idx].v0 = prep.current_speed; + jlog.data[jlog.idx].a0 = prep.last_accel; + jlog.data[jlog.idx].da = jlog.idx == 0 ? prep.last_accel : (prep.last_accel - jlog.data[jlog.idx-1].a0); + jlog.data[jlog.idx].s = jerk_rampdown; + jlog.data[jlog.idx].t = time_to_jerk; #endif + //Distance to 0 acceleration at speed (mm == V(0)*T + 1/2 A0*T^2 + 1/6 J*T^3) + if((mm_remaining - prep.accelerate_until) > jerk_rampdown) { + //+1.0f to avoid divide by 0 speed, minor effect on jerk ramp - ?? + // Check if we are on ramp up or ramp down. Ramp down if distance to end of acceleration is less than distance needed to reach 0 acceleration. + // Then limit acceleration change by jerk up to max acceleration and update for next segment. + // Minimum acceleration jerk per time_var to ensure acceleration completes. Acceleration change at end of ramp is in acceptable jerk range. + prep.last_accel = min(prep.last_accel + accel_var, pl_block->max_acceleration); + } else { +#ifdef JERK_LOG + if(jlog.rd == 0) jlog.rd = jlog.idx; + jlog.data[jlog.idx].ramp_down = true; +#endif + prep.last_accel = max(prep.last_accel - accel_var, accel_var); + } + speed_var = prep.last_accel * time_var; + } else +#endif // ENABLE_JERK_ACCELERATION + speed_var = pl_block->acceleration * time_var; + mm_remaining -= time_var * (prep.current_speed + 0.5f * speed_var); if (mm_remaining < prep.accelerate_until) { // End of acceleration ramp. // Acceleration-cruise, acceleration-deceleration ramp junction, or end of block. @@ -1078,10 +1186,21 @@ void st_prep_buffer (void) prep.ramp_type = mm_remaining == prep.decelerate_after ? Ramp_Decel : Ramp_Cruise; prep.current_speed = prep.maximum_speed; #if ENABLE_JERK_ACCELERATION - last_segment_accel = 0.0f; // reset acceleration variable to 0 for next accel ramp + if(prep.jerk) { + prep.last_accel = 0.0f; // reset acceleration variable to 0 for next accel ramp +#ifdef JERK_LOG + if(prep.ramp_type == Ramp_Decel) jlog.d = jlog.idx; #endif + } +#endif // ENABLE_JERK_ACCELERATION } else // Acceleration only. prep.current_speed += speed_var; +#ifdef JERK_LOG + jlog.data[jlog.idx].accel = prep.ramp_type == Ramp_Accel; + jlog.data[jlog.idx].v0 = prep.current_speed; + jlog.data[jlog.idx].time_var = time_var; + jlog.data[jlog.idx].mm_remaining = mm_remaining; +#endif break; case Ramp_Cruise: @@ -1094,6 +1213,9 @@ void st_prep_buffer (void) time_var = (mm_remaining - prep.decelerate_after) / prep.maximum_speed; mm_remaining = prep.decelerate_after; // NOTE: 0.0 at EOB prep.ramp_type = Ramp_Decel; +#ifdef JERK_LOG + if(jlog.d == 0) jlog.d = jlog.idx; +#endif } else // Cruising only. mm_remaining = mm_var; break; @@ -1101,20 +1223,37 @@ void st_prep_buffer (void) default: // case Ramp_Decel: // NOTE: mm_var used as a misc worker variable to prevent errors when near zero speed. #if ENABLE_JERK_ACCELERATION - time_to_jerk = last_segment_accel / pl_block->jerk; - jerk_rampdown = prep.exit_speed + time_to_jerk * (last_segment_accel - (0.5f * pl_block->jerk * time_to_jerk)); // Speedpoint to start ramping down deceleration. (V = a * t - 1/2 j * t^2) - if (prep.current_speed > jerk_rampdown) { - // Check if we are on ramp up or ramp down. Ramp down if speed is less than speed needed for reaching 0 acceleration. - // Then limit acceleration change by jerk up to max acceleration and update for next segment. - // Minimum acceleration of jerk per time_var to ensure deceleration completes. Acceleration change at end of ramp is in acceptable jerk range. - last_segment_accel = min(last_segment_accel + pl_block->jerk * time_var, pl_block->max_acceleration); - } else { - last_segment_accel = max(last_segment_accel - pl_block->jerk * time_var, pl_block->jerk * time_var); - } - speed_var = last_segment_accel * time_var; // Used as delta speed (mm/min) -#else - speed_var = pl_block->acceleration * time_var; // Used as delta speed (mm/min) + if(prep.jerk) { + float accel_var = pl_block->jerk * time_var; // Delta acceleration + float time_to_jerk = prep.last_accel == 0.0f ? accel_var : (prep.last_accel / pl_block->jerk); + float jerk_rampdown = prep.exit_speed + + time_to_jerk * (prep.last_accel - + (0.5f * pl_block->jerk * time_to_jerk)); // Speedpoint to start ramping down deceleration. (V = a * t - 1/2 j * t^2) +#ifdef JERK_LOG + jlog.data[jlog.idx].s0 = prep.decelerate_after - mm_remaining; + jlog.data[jlog.idx].v0 = prep.current_speed; + jlog.data[jlog.idx].a0 = prep.last_accel; + jlog.data[jlog.idx].da = jlog.idx == 0 ? prep.last_accel : (prep.last_accel - jlog.data[jlog.idx-1].a0); + jlog.data[jlog.idx].s = jerk_rampdown; + jlog.data[jlog.idx].t = time_to_jerk; #endif + if(prep.current_speed > jerk_rampdown) { + // Check if we are on ramp up or ramp down. Ramp down if speed is less than speed needed for reaching 0 acceleration. + // Then limit acceleration change by jerk up to max acceleration and update for next segment. + // Minimum acceleration of jerk per time_var to ensure deceleration completes. Acceleration change at end of ramp is in acceptable jerk range. + prep.last_accel = min(prep.last_accel + accel_var, pl_block->max_acceleration); + } else { +#ifdef JERK_LOG + if(jlog.ru == 0) jlog.ru = jlog.idx; + jlog.data[jlog.idx].ramp_down = true; +#endif + prep.last_accel = max(prep.last_accel - accel_var, accel_var); + } + speed_var = prep.last_accel * time_var; // Used as delta speed (mm/min) + } else +#endif //ENABLE_JERK_ACCELERATION + speed_var = pl_block->acceleration * time_var; // Used as delta speed (mm/min) + if (prep.current_speed > speed_var) { // Check if at or below zero speed. // Compute distance from end of segment to end of block. mm_var = mm_remaining - time_var * (prep.current_speed - 0.5f * speed_var); // (mm) @@ -1125,14 +1264,25 @@ void st_prep_buffer (void) } } // Otherwise, at end of block or end of forced-deceleration. +#if ENABLE_JERK_ACCELERATION + if(prep.jerk) { + time_var = 2.0f * (mm_remaining - prep.mm_complete) / (prep.current_speed + prep.exit_speed); +// prep.last_accel = 0.0f; // reset acceleration variable to 0 for next accel ramp + } else +#endif time_var = 2.0f * (mm_remaining - prep.mm_complete) / (prep.current_speed + prep.exit_speed); + mm_remaining = prep.mm_complete; prep.current_speed = prep.exit_speed; -#if ENABLE_JERK_ACCELERATION - last_segment_accel = 0.0f; // reset acceleration variable to 0 for next accel ramp -#endif } +#ifdef JERK_LOG + jlog.data[jlog.idx].v = prep.current_speed; + jlog.data[jlog.idx].accel = prep.ramp_type == Ramp_Accel; + jlog.data[jlog.idx].time_var = time_var; + jlog.data[jlog.idx].mm_remaining = mm_remaining; +#endif + dt += time_var; // Add computed ramp time to total segment time. if (dt < dt_max) @@ -1234,6 +1384,16 @@ void st_prep_buffer (void) prep_segment->target_position = prep.target_position; //st_prep_block->millimeters - pl_block->millimeters; } + +#ifdef JERK_LOG +if(jlog.idx < sizeof(jlog.data) - 1 && prep.ramp_type != Ramp_Cruise) { + jlog.data[jlog.idx].n_step = prep_segment->n_step; + jlog.data[jlog.idx].acc_step = jlog.idx == 0 ? prep_segment->n_step : jlog.data[jlog.idx-1].acc_step + prep_segment->n_step; + jlog.data[jlog.idx].time = cycles; + jlog.idx++; +} +#endif + #if ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING // Compute step timing and multi-axis smoothing level. // NOTE: AMASS overdrives the timer with each level, so only one prescalar is required. diff --git a/stepper.h b/stepper.h index e5ea71e..5fc8640 100644 --- a/stepper.h +++ b/stepper.h @@ -96,6 +96,30 @@ typedef struct stepper { segment_t *exec_segment; //!< Pointer to the segment being executed. } stepper_t; +#if ENABLE_JERK_ACCELERATION + +//#define JERK_LOG 400 + +#ifdef JERK_LOG + +typedef struct { + uint32_t idx, rd, d, ru; + float accel, max_accel, jerk; + struct { + float s, s0, v, v0, a0, da, t, mm_remaining, time_var; + uint32_t time; + uint32_t n_step; + uint32_t acc_step; + bool accel; // accelerating + bool ramp_down; // accel ramp down + } data[400]; + +} jlog_t; + +#endif + +#endif + // Initialize and setup the stepper motor subsystem void stepper_init (void); diff --git a/stream.c b/stream.c index dab8976..5e1b7af 100644 --- a/stream.c +++ b/stream.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2021-2025 Terje Io + Copyright (c) 2021-2026 Terje Io grblHAL is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -546,14 +546,39 @@ void stream_mpg_set_mode (void *data) stream_mpg_enable(data != NULL); } +static void stream_mpg_write (void *cmd) +{ + switch((uint32_t)cmd) { + + case CMD_STATUS_REPORT_ALL: + report_realtime_status(mpg.stream.write, report_get_rt_flags_all()); + break; + + case CMD_GCODE_REPORT: + report_gcode_modes(mpg.stream.write); + break; + } +} + ISR_CODE bool ISR_FUNC(stream_mpg_check_enable)(uint8_t c) { - if(c == CMD_MPG_MODE_TOGGLE) - task_add_immediate(stream_mpg_set_mode, (void *)1); - else { - protocol_enqueue_realtime_command(c); - if((c == CMD_CYCLE_START || c == CMD_CYCLE_START_LEGACY) && settings.status_report.pin_state) - sys.report.cycle_start |= state_get() == STATE_IDLE; + switch(c) { + + case CMD_MPG_MODE_TOGGLE: + task_add_immediate(stream_mpg_set_mode, (void *)1); + break; + + case CMD_GCODE_REPORT: + case CMD_STATUS_REPORT_ALL: + if(mpg.flags.is_mpg_tx) + task_add_immediate(stream_mpg_write, (void *)((uint32_t)c)); + break; + + default: + protocol_enqueue_realtime_command(c); + if((c == CMD_CYCLE_START || c == CMD_CYCLE_START_LEGACY) && settings.status_report.pin_state) + sys.report.cycle_start |= state_get() == STATE_IDLE; + break; } return true; diff --git a/system.c b/system.c index 607df6d..316f349 100644 --- a/system.c +++ b/system.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2025 Terje Io + Copyright (c) 2017-2026 Terje Io Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC grblHAL is free software: you can redistribute it and/or modify @@ -324,7 +324,7 @@ static status_code_t output_all_settings (sys_state_t state, char *args) static status_code_t output_parser_state (sys_state_t state, char *args) { - report_gcode_modes(); + report_gcode_modes(hal.stream.write); system_add_rt_report(Report_Homed); // Report homed state on next realtime report return Status_OK; @@ -535,6 +535,13 @@ static status_code_t home_v (sys_state_t state, char *args) } #endif +#ifdef W_AXIS +static status_code_t home_w (sys_state_t state, char *args) +{ + return go_home(state, (axes_signals_t){W_AXIS_BIT}); +} +#endif + static status_code_t enter_sleep (sys_state_t state, char *args) { if(!settings.flags.sleep_enable) @@ -930,32 +937,23 @@ PROGMEM static const sys_command_t sys_commands[] = { { "HX", home_x }, { "HY", home_y }, { "HZ", home_z }, -#if AXIS_REMAP_ABC2UVW - #ifdef A_AXIS - { "HU", home_a }, - #endif - #ifdef B_AXIS - { "HV", home_b }, - #endif - #ifdef C_AXIS - { "HW", home_c }, - #endif -#else - #ifdef A_AXIS +#ifdef A_AXIS { "HA", home_a }, - #endif - #ifdef B_AXIS +#endif +#ifdef B_AXIS { "HB", home_b }, - #endif - #ifdef C_AXIS +#endif +#ifdef C_AXIS { "HC", home_c }, - #endif #endif #ifdef U_AXIS { "HU", home_u }, #endif #ifdef V_AXIS { "HV", home_v }, +#endif +#ifdef W_AXIS + { "HW", home_w }, #endif { "HSS", report_current_home_signal_state, { .noargs = On, .allow_blocking = On }, { .str = "report homing switches status" } }, { "HELP", output_help, { .allow_blocking = On }, { @@ -1133,26 +1131,6 @@ status_code_t system_execute_line (char *line) cmd = retval == Status_Unhandled ? cmd->next : NULL; } while(cmd); - // deprecated, to be removed - if(retval == Status_Unhandled && (cmd = grbl.on_get_commands ? grbl.on_get_commands() : NULL)) { - - do { - for(idx = 0; idx < cmd->n_commands; idx++) { - if(!strcmp(line, cmd->commands[idx].command)) { - if(sys.blocking_event && !cmd->commands[idx].flags.allow_blocking) { - retval = Status_NotAllowedCriticalEvent; - break; - } else if(!cmd->commands[idx].flags.noargs || args == NULL) { - if((retval = cmd->commands[idx].execute(state_get(), args)) != Status_Unhandled) - break; - } - } - } - cmd = retval == Status_Unhandled && cmd->on_get_commands ? cmd->on_get_commands() : NULL; - } while(cmd); - } - // end of to be removed - // Let user code have a peek at system commands before check for global setting if(retval == Status_Unhandled && grbl.on_unknown_sys_command) { if(args) @@ -1252,11 +1230,12 @@ bool system_xy_at_fixture (coord_system_id_t id, float tolerance) { bool ok = false; - coord_data_t target, position; + coord_data_t position; + coord_system_data_t target; - if(tolerance > 0.0f && settings_read_coord_data(id, &target.values)) { + if(tolerance > 0.0f && settings_read_coord_data(id, &target)) { system_convert_array_steps_to_mpos(position.values, sys.position); - ok = hypot_f(position.x - target.x, position.y - target.y) <= tolerance; + ok = hypot_f(position.x - target.coord.x, position.y - target.coord.y) <= tolerance; } return ok; diff --git a/task.h b/task.h index 3abc522..4018264 100644 --- a/task.h +++ b/task.h @@ -31,4 +31,6 @@ void task_delete (foreground_task_ptr fn, void *data); bool task_add_systick (foreground_task_ptr fn, void *data); void task_delete_systick (foreground_task_ptr fn, void *data); +void task_raise_alarm (void *data); + #endif // _CORE_TASK_H_ diff --git a/tool_change.c b/tool_change.c index 8253493..9c66f66 100644 --- a/tool_change.c +++ b/tool_change.c @@ -62,12 +62,12 @@ static void onHomingComplete (axes_signals_t homing_cycle, bool success) system_clear_tlo_reference(homing_cycle); } -static void onWcoSaved (coord_system_id_t id, coord_data_t *offset) +static void onWcoSaved (coord_system_id_t id, coord_system_data_t *data) { if(on_wco_saved) - on_wco_saved(id, offset); + on_wco_saved(id, data); - if(id == gc_state.modal.coord_system.id && block_cycle_start) + if(id == gc_state.modal.g5x_offset.id && block_cycle_start) block_cycle_start = change_at_g30; } @@ -198,8 +198,11 @@ static bool go_linear_home (plan_line_data_t *pl_data) static bool go_toolsetter (plan_line_data_t *pl_data) { + coord_system_data_t g59_3_offset; + // G59.3 contains offsets to toolsetter. - settings_read_coord_data(CoordinateSystem_G59_3, &target.values); + settings_read_coord_data(CoordinateSystem_G59_3, &g59_3_offset); + memcpy(target.values, g59_3_offset.coord.values, sizeof(float) * 3); // move only XYZ float tmp_pos = target.values[plane.axis_linear]; @@ -294,27 +297,27 @@ static void execute_probe (void *data) { #if COMPATIBILITY_LEVEL <= 1 bool ok; - coord_data_t offset; plan_line_data_t plan_data; gc_parser_flags_t flags = {}; + coord_system_data_t g59_3_offset; // G59.3 contains offsets to position of TLS. - settings_read_coord_data(CoordinateSystem_G59_3, &offset.values); + settings_read_coord_data(CoordinateSystem_G59_3, &g59_3_offset); plan_data_init(&plan_data); plan_data.condition.rapid_motion = On; ok = !change_at_g30 || go_linear_home(&plan_data); - target.values[plane.axis_0] = offset.values[plane.axis_0]; - target.values[plane.axis_1] = offset.values[plane.axis_1]; + target.values[plane.axis_0] = g59_3_offset.coord.values[plane.axis_0]; + target.values[plane.axis_1] = g59_3_offset.coord.values[plane.axis_1]; if(probe_toolsetter) grbl.on_probe_toolsetter(next_tool, &target, false, true); if((ok = ok && mc_line(target.values, &plan_data))) { - target.values[plane.axis_linear] = offset.values[plane.axis_linear]; + target.values[plane.axis_linear] = g59_3_offset.coord.values[plane.axis_linear]; ok = mc_line(target.values, &plan_data); plan_data.feed_rate = settings.tool_change.seek_rate; @@ -508,9 +511,11 @@ static status_code_t tool_change (parser_state_t *parser_state) // tool_change_position = ? //else - if((change_at_g30 = (settings.flags.tool_change_at_g30) && (sys.homed.mask & (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT)) == (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT))) - settings_read_coord_data(CoordinateSystem_G30, &change_position.values); - else + if((change_at_g30 = settings.flags.tool_change_at_g30 && (sys.homed.mask & (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT)) == (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT))) { + coord_system_data_t g30_offset; + settings_read_coord_data(CoordinateSystem_G30, &g30_offset); + memcpy(change_position.values, g30_offset.coord.values, sizeof(float) * 3); // move only XYZ + } else change_position.values[plane.axis_linear] = sys.home_position[plane.axis_linear]; // - settings.homing.flags.force_set_origin ? LINEAR_AXIS_HOME_OFFSET : 0.0f; // Rapid to home position of linear axis.