Changed signature of grbl.on_homing complete event to include the cycle flags.

Added definitions for up to four additional digital aux I/O ports.
Added real time report of selected spindle in multi spindle configurations. Reported on changes only.
Removed limits override input invert config, for safety reasons it is always active low.
Added HAL entry points for second RGB channel, renamed first from hal.rgb to hal.rgb0.
Added option to setting $22 to force use of limit switches for homing when homing inputs are available in the driver/board combo.
Improved handling of aux I/O pins when claimed for core functions.
Added flag to $9 for disabling laser mode capability for primary PWM spindle. Allows leaving laser mode enabled when a secondary PWM spindle is available and this is used to control a laser.
Added some generic setting definitions for stepper drivers, currently used by the motors plugin.
This commit is contained in:
Terje Io
2024-03-19 20:32:40 +01:00
parent 06f442643a
commit 7cf86877f0
28 changed files with 1092 additions and 224 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ It has been written to complement grblHAL and has features such as proper keyboa
---
Latest build date is 20240222, see the [changelog](changelog.md) for details.
Latest build date is 20240318, see the [changelog](changelog.md) for details.
__NOTE:__ Build 20240222 has moved the probe input to the ioPorts pool of inputs and will be allocated from it when configured.
The change is major and _potentially dangerous_, it may damage your probe, so please _verify correct operation_ after installing this, or later, builds.
+56
View File
@@ -1,5 +1,61 @@
## grblHAL changelog
<a name="20240318"/>Build 20240318
Core:
* Changed signature of `grbl.on_homing complete` event to include the cycle flags.
* Added definitions for up to four additional digital aux I/O ports.
* Added real time report of selected spindle in multi spindle configurations. Reported on changes only.
* Removed limits override input invert config, for safety reasons it is always active low.
* Added HAL entry points for second RGB channel, renamed first from `hal.rgb` to `hal.rgb0`.
* Added option to setting `$22` to force use of limit switches for homing when homing inputs are available in the driver/board combo.
* Improved handling of aux I/O pins when claimed for core functions.
* Added flag to `$9` for disabling laser mode capability for primary PWM spindle. Allows leaving laser mode enabled when a
secondary PWM spindle is available and this is used to control a laser.
* Added some generic setting definitions for stepper drivers, currently used by the motors plugin.
Drivers:
* STM32F4xx: added support for secondary PWM spindle, home signal inputs and preliminary support for the Sienci SLB board. Moved PWM spindle code to separate file.
Added full WebUI support for F412 and F429 MCUs, others may work but with settings missing due to limited RAM.
Merged some code/adopted ideas from the Sienci SLB project for bitbanged Neopixel support and `$DFU` command for entering DFU bootloader mode \(via USB only for now\).
* STM32F7xx: added support for secondary PWM spindle. Moved PWM spindle code to separate file. Added tentative support for F765 MCU. Some PWM bug fixes.
* ESP32: added 6pack v2 board, fixes for v1 definitions - from [PR #103](https://github.com/grblHAL/ESP32/pull/103). Added driver support for max limit switches and missing init for e-stop input.
* iMXRT1062, STM32F4xx, STM32F7xx and MSP432: updated for core change related to spindle at speed handling.
* RP2040: fix for [issue #83](https://github.com/grblHAL/RP2040/issues/83), missing code guards.
* iMXRT1062, STM32F4xx, RP2040 and ESP32: updated for core change related to the RGB HAL.
Plugins:
* Motors: updated to match improved Trinamic low level driver API. Added optional settings for some tuning parameters and made default symbols overridable.
Merged some code/adopted ideas from the Sienci SLB project for new functionality.
Added option for routing StallGuard signals to homing inputs when supported by the driver.
__NOTE:__ some of these changes has only been lightly tested.
* Spindle: updated for core changes, switched to shared code for PWM spindle configuration.
* Keypad: limited code guard for enabling keypad plugin to 1 - 3 range to allow other implementations.
* Plasma: corrected messed up settings handling.
* Trinamic drivers: improved configuration handling/inheritance, adapted support for TMC2660 from the Sienci SLB project. Some generic changes to improve consistencty among drivers.
---
<a name="20240228"/>Build 20240228
Core:
+28 -4
View File
@@ -5,18 +5,18 @@
Copyright (c) 2020-2024 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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
/*! \file
@@ -1326,6 +1326,16 @@ to a reset during motion.
#endif
///@}
/*! /def DEFAULT_HOMING_USE_LIMIT_SWITCHES
\brief
Enable this setting to force using limit switches for homing.
\internal Bit 7 in settings.homing.flags.
*/
#if !defined DEFAULT_HOMING_USE_LIMIT_SWITCHES || defined __DOXYGEN__
#define DEFAULT_HOMING_USE_LIMIT_SWITCHES Off // Default disabled. Set to \ref On or 1 to enable.
#endif
///@}
/*! @name $23 - Setting_HomingDirMask
\ref axismask controlling the direction of movement during homing.
Unset bits in the mask results in movement in positive direction.
@@ -1454,6 +1464,20 @@ greater.
#endif
///@}
/*! @name $671 - Setting_HomePinsInvertMask
By default, grblHAL sets all input pins to normal-low operation with their internal pull-up resistors
enabled. This simplifies the wiring for users by requiring only a normally closed (NC) switch connected
to ground. It is _not_ recommended to use normally-open (NO) switches as this increases the risk
of electrical noise or cable breaks spuriously triggering the inputs. If normally-open (NO) switches
are used the logic of the input signals should be be inverted with the \ref axismask below.
*/
///@{
#if !defined DEFAULT_HOME_SIGNALS_INVERT_MASK || defined __DOXYGEN__
#define DEFAULT_HOME_SIGNALS_INVERT_MASK 0 // Set to -1 or AXES_BITMASK to invert for all axes
#endif
///@}
// Probing settings (Group_Probing)
/*! @name $6 - Setting_InvertProbePin
+8 -5
View File
@@ -5,18 +5,18 @@
Copyright (c) 2020-2024 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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
/*! \file
@@ -103,7 +103,10 @@ typedef void (*on_unknown_feedback_message_ptr)(stream_write_ptr stream_write);
typedef void (*on_stream_changed_ptr)(stream_type_t type);
typedef bool (*on_laser_ppi_enable_ptr)(uint_fast16_t ppi, uint_fast16_t pulse_length);
typedef void (*on_homing_rate_set_ptr)(axes_signals_t axes, float rate, homing_mode_t mode);
typedef void (*on_homing_completed_ptr)(bool success);
// NOTE: cycle contains the axis flags of the executed homing cycle, success will be true when all the configured cycles are completed.
typedef void (*on_homing_completed_ptr)(axes_signals_t cycle, bool success);
typedef bool (*on_probe_fixture_ptr)(tool_data_t *tool, bool at_g59_3, bool on);
typedef bool (*on_probe_start_ptr)(axes_signals_t axes, float *target, plan_line_data_t *pl_data);
typedef void (*on_probe_completed_ptr)(void);
+49 -18
View File
@@ -48,14 +48,17 @@ typedef enum {
Input_LimitX_2,
Input_LimitX_Max,
Input_HomeX,
Input_HomeX_2,
Input_LimitY,
Input_LimitY_2,
Input_LimitY_Max,
Input_HomeY,
Input_HomeY_2,
Input_LimitZ,
Input_LimitZ_2,
Input_LimitZ_Max,
Input_HomeZ,
Input_HomeZ_2,
Input_LimitA,
Input_LimitA_Max,
Input_HomeA,
@@ -81,7 +84,11 @@ typedef enum {
Input_Aux5,
Input_Aux6,
Input_Aux7,
Input_AuxMax = Input_Aux7,
Input_Aux8,
Input_Aux9,
Input_Aux10,
Input_Aux11,
Input_AuxMax = Input_Aux11,
Input_Analog_Aux0,
Input_Analog_Aux1,
Input_Analog_Aux2,
@@ -139,6 +146,9 @@ typedef enum {
Output_SpindleOn,
Output_SpindleDir,
Output_SpindlePWM,
Output_Spindle1On,
Output_Spindle1Dir,
Output_Spindle1PWM,
Output_CoolantMist,
Output_CoolantFlood,
Output_Aux0,
@@ -149,7 +159,11 @@ typedef enum {
Output_Aux5,
Output_Aux6,
Output_Aux7,
Output_AuxMax = Output_Aux7,
Output_Aux8,
Output_Aux9,
Output_Aux10,
Output_Aux11,
Output_AuxMax = Output_Aux11,
Output_Analog_Aux0,
Output_Analog_Aux1,
Output_Analog_Aux2,
@@ -165,6 +179,8 @@ typedef enum {
Output_LED_B,
Output_LED_W,
Output_LED_Adressable,
Output_LED0_Adressable = Output_LED_Adressable,
Output_LED1_Adressable,
// Multipin peripherals
Input_MISO,
Multipin = Input_MISO,
@@ -229,32 +245,39 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Input_LimitX_2, .name = "X limit min 2" },
{ .function = Input_LimitX_Max, .name = "X limit max" },
{ .function = Input_HomeX, .name = "X home" },
{ .function = Input_HomeX_2, .name = "X home 2" },
{ .function = Input_LimitY, .name = "Y limit min" },
{ .function = Input_LimitY_2, .name = "Y limit min 2" },
{ .function = Input_LimitY_Max, .name = "Y limit max" },
{ .function = Input_HomeY, .name = "Y home" },
{ .function = Input_HomeY_2, .name = "Y home 2" },
{ .function = Input_LimitZ, .name = "Z limit min" },
{ .function = Input_LimitZ_2, .name = "Z limit min 2" },
{ .function = Input_LimitZ_Max, .name = "Z limit max" },
{ .function = Input_HomeZ, .name = "Z home" },
{ .function = Input_HomeZ_2, .name = "Z home 2" },
{ .function = Input_SpindleIndex, .name = "Spindle index" },
{ .function = Input_SpindlePulse, .name = "Spindle pulse" },
{ .function = Input_Aux0, .name = "Aux input 0" },
{ .function = Input_Aux1, .name = "Aux input 1" },
{ .function = Input_Aux2, .name = "Aux input 2" },
{ .function = Input_Aux3, .name = "Aux input 3" },
{ .function = Input_Aux4, .name = "Aux input 4" },
{ .function = Input_Aux5, .name = "Aux input 5" },
{ .function = Input_Aux6, .name = "Aux input 6" },
{ .function = Input_Aux7, .name = "Aux input 7" },
{ .function = Input_Analog_Aux0, .name = "Aux analog input 0" },
{ .function = Input_Analog_Aux1, .name = "Aux analog input 1" },
{ .function = Input_Analog_Aux2, .name = "Aux analog input 2" },
{ .function = Input_Analog_Aux3, .name = "Aux analog input 3" },
{ .function = Input_Analog_Aux4, .name = "Aux analog input 4" },
{ .function = Input_Analog_Aux5, .name = "Aux analog input 5" },
{ .function = Input_Analog_Aux6, .name = "Aux analog input 6" },
{ .function = Input_Analog_Aux7, .name = "Aux analog input 7" },
{ .function = Input_Aux0, .name = "Aux in 0" },
{ .function = Input_Aux1, .name = "Aux in 1" },
{ .function = Input_Aux2, .name = "Aux in 2" },
{ .function = Input_Aux3, .name = "Aux in 3" },
{ .function = Input_Aux4, .name = "Aux in 4" },
{ .function = Input_Aux5, .name = "Aux in 5" },
{ .function = Input_Aux6, .name = "Aux in 6" },
{ .function = Input_Aux7, .name = "Aux in 7" },
{ .function = Input_Aux8, .name = "Aux in 8" },
{ .function = Input_Aux9, .name = "Aux in 9" },
{ .function = Input_Aux10, .name = "Aux in 10" },
{ .function = Input_Aux11, .name = "Aux in 11" },
{ .function = Input_Analog_Aux0, .name = "Aux analog in 0" },
{ .function = Input_Analog_Aux1, .name = "Aux analog in 1" },
{ .function = Input_Analog_Aux2, .name = "Aux analog in 2" },
{ .function = Input_Analog_Aux3, .name = "Aux analog in 3" },
{ .function = Input_Analog_Aux4, .name = "Aux analog in 4" },
{ .function = Input_Analog_Aux5, .name = "Aux analog in 5" },
{ .function = Input_Analog_Aux6, .name = "Aux analog in 6" },
{ .function = Input_Analog_Aux7, .name = "Aux analog in 7" },
{ .function = Output_StepX, .name = "X step" },
{ .function = Output_StepX_2, .name = "X2 step" },
{ .function = Output_StepY, .name = "Y step" },
@@ -326,6 +349,9 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Output_SpindleOn, .name = "Spindle on" },
{ .function = Output_SpindleDir, .name = "Spindle direction" },
{ .function = Output_SpindlePWM, .name = "Spindle PWM" },
{ .function = Output_Spindle1On, .name = "Spindle 2 on" },
{ .function = Output_Spindle1Dir, .name = "Spindle 2 direction" },
{ .function = Output_Spindle1PWM, .name = "Spindle 2 PWM" },
{ .function = Output_CoolantMist, .name = "Mist" },
{ .function = Output_CoolantFlood, .name = "Flood" },
{ .function = Output_Aux0, .name = "Aux out 0" },
@@ -336,6 +362,10 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Output_Aux5, .name = "Aux out 5" },
{ .function = Output_Aux6, .name = "Aux out 6" },
{ .function = Output_Aux7, .name = "Aux out 7" },
{ .function = Output_Aux8, .name = "Aux out 8" },
{ .function = Output_Aux9, .name = "Aux out 9" },
{ .function = Output_Aux10, .name = "Aux out 10" },
{ .function = Output_Aux11, .name = "Aux out 11" },
{ .function = Output_Analog_Aux0, .name = "Aux analog out 0" },
{ .function = Output_Analog_Aux1, .name = "Aux analog out 1" },
{ .function = Output_Analog_Aux2, .name = "Aux analog out 2" },
@@ -350,6 +380,7 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Output_LED_B, .name = "LED B" },
{ .function = Output_LED_W, .name = "LED W" },
{ .function = Output_LED_Adressable, .name = "LED adressable" },
{ .function = Output_LED1_Adressable, .name = "LED adressable 1" },
{ .function = Input_MISO, .name = "MISO" },
{ .function = Output_MOSI, .name = "MOSI" },
{ .function = Output_SPICLK, .name = "SPI CLK" },
+3 -3
View File
@@ -189,7 +189,7 @@
#else
#define TRINAMIC_UART_ENABLE 0
#endif
#if (TRINAMIC_ENABLE == 2130 || TRINAMIC_ENABLE == 5160)
#if (TRINAMIC_ENABLE == 2130 || TRINAMIC_ENABLE == 2660 || TRINAMIC_ENABLE == 5160)
#if !defined(TRINAMIC_SPI_ENABLE)
#define TRINAMIC_SPI_ENABLE 1
#endif
@@ -314,11 +314,11 @@
#if SPINDLE_ENABLE & ((1<<SPINDLE_PWM1)|(1<<SPINDLE_PWM1_NODIR))
#define DRIVER_SPINDLE1_PWM_ENABLE 1
#define DRIVER_SPINDLE1_NAME "PWM"
#define DRIVER_SPINDLE1_NAME "PWM2"
#else
#define DRIVER_SPINDLE1_PWM_ENABLE 0
#if DRIVER_SPINDLE1_ENABLE
#define DRIVER_SPINDLE1_NAME "Basic"
#define DRIVER_SPINDLE1_NAME "Basic2"
#endif
#endif
+17 -13
View File
@@ -756,7 +756,7 @@ status_code_t gc_execute_block (char *block)
// Determine if the line is a program start/end marker.
// Old comment from protocol.c:
// NOTE: This maybe installed to tell Grbl when a program is running vs manual input,
// NOTE: This maybe installed to tell grblHAL when a program is running vs manual input,
// where, during a program, the system auto-cycle start will continue to execute
// everything until the next '%' sign. This will help fix resuming issues with certain
// functions that empty the planner buffer to execute its task on-time.
@@ -777,7 +777,7 @@ status_code_t gc_execute_block (char *block)
memset(&gc_block, 0, sizeof(gc_block)); // Initialize the parser block struct.
memcpy(&gc_block.modal, &gc_state.modal, sizeof(gc_state.modal)); // Copy current modes
bool set_tool = false, spindle_programmed = false;
bool set_tool = false, spindle_event = false;
axis_command_t axis_command = AxisCommand_None;
io_mcode_t port_command = (io_mcode_t)0;
plane_t plane;
@@ -1581,7 +1581,7 @@ status_code_t gc_execute_block (char *block)
To do this, this would simply need to retain all of the data in STEP 1, such as the new block
data struct, the modal group and value bitflag tracking variables, and axis array indices
compatible variables. This data contains all of the information necessary to error-check the
new g-code block when the EOL character is received. However, this would break Grbl's startup
new g-code block when the EOL character is received. However, this would break grblHAL's startup
lines in how it currently works and would require some refactoring to make it compatible.
*/
@@ -1736,7 +1736,7 @@ status_code_t gc_execute_block (char *block)
gc_state.modal.spindle.rpm_mode = gc_block.modal.spindle.rpm_mode;
}
spindle_programmed = gc_block.words.s && !user_words.s;
spindle_event = gc_block.words.s && !user_words.s;
if (!gc_block.words.s)
gc_block.values.s = gc_state.modal.spindle.rpm_mode == SpindleSpeedMode_RPM ? gc_state.spindle.rpm : gc_state.spindle.hal->param->css.max_rpm;
@@ -2049,7 +2049,7 @@ status_code_t gc_execute_block (char *block)
// [13. Cutter radius compensation ]: G41/42 NOT SUPPORTED. Error, if enabled while G53 is active.
// [G40 Errors]: G2/3 arc is programmed after a G40. The linear move after disabling is less than tool diameter.
// NOTE: Since cutter radius compensation is never enabled, these G40 errors don't apply. Grbl supports G40
// NOTE: Since cutter radius compensation is never enabled, these G40 errors don't apply. grblHAL supports G40
// only for the purpose to not error when G40 is sent with a g-code program header to setup the default modes.
// [14. Tool length compensation ]: G43.1 and G49 are always supported, G43 and G43.2 if grbl.tool_table.n_tools > 0
@@ -3160,31 +3160,35 @@ status_code_t gc_execute_block (char *block)
}
// [7. Spindle control ]:
if (gc_state.modal.spindle.state.value != gc_block.modal.spindle.state.value) {
if(gc_state.modal.spindle.state.value != gc_block.modal.spindle.state.value) {
// Update spindle control and apply spindle speed when enabling it in this block.
// NOTE: All spindle state changes are synced, even in laser mode. Also, plan_data,
// rather than gc_state, is used to manage laser state for non-laser motions.
bool spindle_ok = false;
if(gc_block.spindle) {
if((spindle_programmed = spindle_sync(gc_block.spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm)))
if(grbl.on_spindle_programmed)
grbl.on_spindle_programmed(gc_block.spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm, gc_block.modal.spindle.rpm_mode);
if((spindle_ok = spindle_sync(gc_block.spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm)))
gc_block.spindle->param->state = gc_block.modal.spindle.state;
} else {
idx = N_SYS_SPINDLE;
do {
if(spindle_is_enabled(--idx)) {
spindle_ptrs_t *spindle = spindle_get(idx);
if(spindle_sync(spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm)) {
spindle_programmed = true;
if(grbl.on_spindle_programmed)
grbl.on_spindle_programmed(spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm, gc_block.modal.spindle.rpm_mode);
if(spindle_sync(spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm))
spindle->param->state = gc_block.modal.spindle.state;
}
else
spindle_ok = false;
}
} while(idx);
}
if(spindle_programmed)
if(!(spindle_event = !spindle_ok))
gc_state.modal.spindle.state = gc_block.modal.spindle.state;
}
// TODO: add spindle argument and move into loop above?
if(spindle_programmed && grbl.on_spindle_programmed)
if(spindle_event && grbl.on_spindle_programmed)
grbl.on_spindle_programmed(gc_state.spindle.hal, gc_state.modal.spindle.state, gc_state.spindle.rpm, gc_state.modal.spindle.rpm_mode);
// TODO: Recheck spindle running in CCS mode (is_rpm_pos_adjusted == On)?
+8 -8
View File
@@ -1,23 +1,23 @@
/*
grbl.h - main Grbl include file for compile time configuration
grbl.h - main grblHAL include file for compile time configuration
Part of grblHAL
Copyright (c) 2017-2024 Terje Io
Copyright (c) 2015-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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _GRBL_H_
@@ -36,13 +36,13 @@
#include "config.h"
// Grbl versioning system
// grblHAL versioning system
#if COMPATIBILITY_LEVEL == 0
#define GRBL_VERSION "1.1f"
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_BUILD 20240228
#define GRBL_BUILD 20240318
#define GRBL_URL "https://github.com/grblHAL"
@@ -134,13 +134,13 @@
// System motion line numbers must be zero.
#define JOG_LINE_NUMBER 0
// Number of blocks Grbl executes upon startup. These blocks are stored in non-volatile storage, where the size
// Number of blocks grblHAL executes upon startup. These blocks are stored in non-volatile storage, where the size
// and addresses are defined in settings.h. With the current settings, up to 2 startup blocks may
// be stored and executed in order. These startup blocks would typically be used to set the g-code
// parser state depending on user preferences.
#define N_STARTUP_LINE 2 // Integer (1-2)
// Number of decimal places (scale) output by Grbl for certain value types. These settings
// Number of decimal places (scale) output by grblHAL for certain value types. These settings
// are determined by realistic and commonly observed values in CNC machines. For example, position
// values cannot be less than 0.001mm or 0.0001in, because machines can not be physically more
// precise this. So, there is likely no need to change these, but you can if you need to here.
+1 -1
View File
@@ -297,7 +297,7 @@ int grbl_enter (void)
sys.driver_started = sys.alarm != Alarm_SelftestFailed;
// "Wire" homing switches to limit switches if not provided by the driver.
if(hal.homing.get_state == NULL)
if(hal.homing.get_state == NULL || settings.homing.flags.use_limit_switches)
hal.homing.get_state = hal.limits_cap.max.mask ? get_homing_status2 : get_homing_status;
if(settings.report_interval)
+2 -1
View File
@@ -598,7 +598,8 @@ typedef struct {
tool_ptrs_t tool; //!< Optional handlers for tool changes.
rtc_ptrs_t rtc; //!< Optional handlers for real time clock (RTC).
io_port_t port; //!< Optional handlers for axuillary I/O (adds support for M62-M66).
rgb_ptr_t rgb; //!< Optional handler for RGB output to LEDs (neopixels) or lamps.
rgb_ptr_t rgb0; //!< Optional handler for RGB output to LEDs (neopixels) or lamps.
rgb_ptr_t rgb1; //!< Optional handler for RGB output to LEDs (neopixels) or lamps.
periph_port_t periph_port; //!< Optional handlers for peripheral pin registration.
driver_reset_ptr driver_reset; //!< Optional handler, called on soft resets. Set to a dummy handler by the core at startup.
nvs_io_t nvs; //!< Optional handlers for storing/retrieving settings and data to/from non-volatile storage (NVS).
+35
View File
@@ -95,6 +95,41 @@ uint8_t ioports_available (io_port_type_t type, io_port_direction_t dir)
return ports;
}
/*! \brief find first free or claimed digital or analog port.
\param type as an \a #io_port_type_t enum value.
\param dir as an \a #io_port_direction_t enum value.
\param description pointer to a \a char constant for the pin description of a previousely claimed port or NULL if searching for the first free port.
\returns the port number if successful, 255 if not.
*/
uint8_t ioport_find_free (io_port_type_t type, io_port_direction_t dir, const char *description)
{
uint8_t port;
bool found = false;
xbar_t *pin;
if(description) {
port = ioports_available(type, dir);
do {
if((pin = hal.port.get_pin_info(type, dir, --port))) {
if((found = pin->description && !strcmp(pin->description, description)))
port = pin->id;
}
} while(port && !found);
}
if(!found) {
port = ioports_available(type, dir);
do {
if((pin = hal.port.get_pin_info(type, dir, --port))) {
if((found = !pin->mode.claimed))
port = pin->id;
}
} while(port && !found);
}
return found ? port : 255;
}
/*! \brief Claim a digital or analog port for exclusive use.
\param type as an \a #io_port_type_t enum value.
\param dir as an \a #io_port_direction_t enum value.
+1
View File
@@ -126,6 +126,7 @@ typedef struct {
uint8_t ioports_available (io_port_type_t type, io_port_direction_t dir);
bool ioport_claim (io_port_type_t type, io_port_direction_t dir, uint8_t *port, const char *description);
bool ioport_can_claim_explicit (void);
uint8_t ioport_find_free (io_port_type_t type, io_port_direction_t dir, const char *description);
bool ioports_enumerate (io_port_type_t type, io_port_direction_t dir, pin_cap_t filter, ioports_enumerate_callback_ptr callback, void *data);
void ioport_assign_function (aux_ctrl_t *aux_ctrl, pin_function_t *function);
void ioport_assign_out_function (aux_ctrl_out_t *aux_ctrl, pin_function_t *function);
+7 -7
View File
@@ -3,24 +3,24 @@
Part of grblHAL
Copyright (c) 2023 Terje Io
Copyright (c) 2023-2024 Terje Io
Transforms derived from mzavatsky at Trossen Robotics
https://hypertriangle.com/~alex/delta-robot-tutorial/
get_cuboid_envelope() derived from javascript code in
https://www.marginallyclever.com/other/samples/fk-ik-test.html
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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../grbl.h"
@@ -527,7 +527,7 @@ static void delta_go_home (void *data)
}
}
static void delta_homing_complete (bool success)
static void delta_homing_complete (axes_signals_t cycle, bool success)
{
kinematics.transform_from_cartesian = transform_from_cartesian;
@@ -546,7 +546,7 @@ static void delta_homing_complete (bool success)
}
if(on_homing_completed)
on_homing_completed(success);
on_homing_completed(cycle, success);
}
static void cancel_jog (sys_state_t state)
+7 -9
View File
@@ -3,22 +3,22 @@
Part of grblHAL
Copyright (c) 2017-2023 Terje Io
Copyright (c) 2017-2024 Terje Io
Copyright (c) 2012-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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
@@ -82,7 +82,7 @@ ISR_CODE static axes_signals_t ISR_FUNC(homing_signals_select)(home_signals_t si
ISR_CODE void ISR_FUNC(limit_interrupt_handler)(limit_signals_t state) // DEFAULT: Limit pin change interrupt process.
{
// Ignore limit switches if already in an alarm state or in-process of executing an alarm.
// When in the alarm state, Grbl should have been reset or will force a reset, so any pending
// When in the alarm state, grblHAL should have been reset or will force a reset, so any pending
// moves in the planner and stream input buffers are all cleared and newly sent blocks will be
// locked out until a homing cycle or a kill lock command. Allows the user to disable the hard
// limit setting if their limits are constantly triggering after a reset and move their axes.
@@ -490,7 +490,7 @@ static bool homing_cycle (axes_signals_t cycle, axes_signals_t auto_square)
}
// The active cycle axes should now be homed and machine limits have been located. By
// default, Grbl defines machine space as all negative, as do most CNCs. Since limit switches
// default, grblHAL defines machine space as all negative, as do most CNCs. Since limit switches
// can be on either side of an axes, check and set axes machine zero appropriately. Also,
// set up pull-off maneuver from axes limit switches that have been homed. This provides
// some initial clearance off the switches and should also help prevent them from falsely
@@ -539,8 +539,6 @@ status_code_t limits_go_home (axes_signals_t cycle)
return Status_LimitsEngaged; // Auto squaring with limit switch asserted is not allowed.
}
tc_clear_tlo_reference(cycle);
return grbl.home_machine(cycle, auto_square) ? Status_OK : Status_Unhandled;
}
+13 -15
View File
@@ -11,18 +11,18 @@
Bezier splines based on a pull request for Marlin by Giovanni Mascellani
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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
@@ -84,7 +84,7 @@ bool mc_line (float *target, plan_line_data_t *pl_data)
#endif
// If enabled, check for soft limit violations. Placed here all line motions are picked up
// from everywhere in Grbl.
// from everywhere in grblHAL.
if(!(pl_data->condition.target_validated && pl_data->condition.target_valid))
limits_soft_check(target, pl_data->condition);
@@ -96,12 +96,12 @@ bool mc_line (float *target, plan_line_data_t *pl_data)
// plan_check_full_buffer() and check for system abort loop. Also for position reporting
// backlash steps will need to be also tracked, which will need to be kept at a system level.
// There are likely some other things that will need to be tracked as well. However, we feel
// that backlash compensation should NOT be handled by Grbl itself, because there are a myriad
// that backlash compensation should NOT be handled by grblHAL itself, because there are a myriad
// of ways to implement it and can be effective or ineffective for different CNC machines. This
// would be better handled by the interface as a post-processor task, where the original g-code
// is translated and inserts backlash motions that best suits the machine.
// NOTE: Perhaps as a middle-ground, all that needs to be sent is a flag or special command that
// indicates to Grbl what is a backlash compensation motion, so that Grbl executes the move but
// indicates to grblHAL what is a backlash compensation motion, so that grblHAL executes the move but
// doesn't update the machine position values. Since the position values used by the g-code
// parser and planner are separate from the system machine positions, this is doable.
@@ -286,7 +286,7 @@ void mc_arc (float *target, plan_line_data_t *pl_data, float *position, float *o
// NOTE: Segment end points are on the arc, which can lead to the arc diameter being smaller by up to
// (2x) settings.arc_tolerance. For 99% of users, this is just fine. If a different arc segment fit
// is desired, i.e. least-squares, midpoint on arc, just change the mm_per_arc_segment calculation.
// For the intended uses of Grbl, this value shouldn't exceed 2000 for the strictest of cases.
// For the intended uses of grblHAL, this value shouldn't exceed 2000 for the strictest of cases.
uint_fast16_t segments = 0;
@@ -816,7 +816,7 @@ void mc_dwell (float seconds)
}
// Perform homing cycle to locate and set machine zero. Only '$H' executes this command.
// NOTE: There should be no motions in the buffer and Grbl must be in an idle state before
// NOTE: There should be no motions in the buffer and grblHAL must be in an idle state before
// executing the homing cycle. This prevents incorrect buffered plans after homing.
status_code_t mc_homing_cycle (axes_signals_t cycle)
{
@@ -830,8 +830,6 @@ status_code_t mc_homing_cycle (axes_signals_t cycle)
if(home_all)
cycle.mask = AXES_BITMASK;
tc_clear_tlo_reference(cycle);
sys.homed.mask |= cycle.mask;
#ifdef KINEMATICS_API
kinematics.limits_set_machine_positions(cycle);
@@ -917,7 +915,7 @@ status_code_t mc_homing_cycle (axes_signals_t cycle)
if(!protocol_execute_realtime()) { // Check for reset and set system abort.
if(grbl.on_homing_completed)
grbl.on_homing_completed(false);
grbl.on_homing_completed(cycle, false);
return Status_Unhandled; // Did not complete. Alarm state set by mc_alarm.
}
@@ -928,7 +926,7 @@ status_code_t mc_homing_cycle (axes_signals_t cycle)
state_set(STATE_IDLE);
if(grbl.on_homing_completed)
grbl.on_homing_completed(false);
grbl.on_homing_completed(cycle, false);
return homed_status;
}
@@ -963,7 +961,7 @@ status_code_t mc_homing_cycle (axes_signals_t cycle)
limits_set_work_envelope();
if(grbl.on_homing_completed)
grbl.on_homing_completed(homed_status == Status_OK);
grbl.on_homing_completed(cycle, homed_status == Status_OK);
return homed_status;
}
@@ -1109,7 +1107,7 @@ void mc_override_ctrl_update (gc_override_flags_t override_state)
}
// Method to ready the system to reset by setting the realtime reset command and killing any
// active processes in the system. This also checks if a system reset is issued while Grbl
// active processes in the system. This also checks if a system reset is issued while grblHAL
// is in a motion state. If so, kills the steppers and sets the system alarm to flag position
// lost, since there was an abrupt uncontrolled deceleration. Called at an interrupt level by
// realtime abort command and hard limits. So, keep to a minimum.
+249 -25
View File
@@ -5,20 +5,20 @@
Part of grblHAL
Copyright (c) 2021-2023 Terje Io
Copyright (c) 2021-2024 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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
@@ -66,6 +66,15 @@
#define X2_DIRECTION_PORT M3_DIRECTION_PORT
#define X2_DIRECTION_PIN M3_DIRECTION_PIN
#define X2_DIRECTION_BIT (1<<M3_DIRECTION_PIN)
#ifdef M3_HOME_PIN
#if X_AUTO_SQUARE
#define X2_HOME_PORT M3_HOME_PORT
#define X2_HOME_PIN M3_HOME_PIN
#define X2_HOME_BIT (1<<M3_HOME_PIN)
#endif
#elif X_AUTO_SQUARE && defined(X_HOME_PIN)
#error "Auto squared X-axis requires second home pin input"
#endif
#ifdef M3_LIMIT_PIN
#if X_AUTO_SQUARE
#define X2_LIMIT_PORT M3_LIMIT_PORT
@@ -101,6 +110,15 @@
#define X2_DIRECTION_PORT M4_DIRECTION_PORT
#define X2_DIRECTION_PIN M4_DIRECTION_PIN
#define X2_DIRECTION_BIT (1<<M4_DIRECTION_PIN)
#ifdef M4_HOME_PIN
#if X_AUTO_SQUARE
#define X2_HOME_PORT M4_HOME_PORT
#define X2_HOME_PIN M4_HOME_PIN
#define X2_HOME_BIT (1<<M4_HOME_PIN)
#endif
#elif X_AUTO_SQUARE && defined(X_HOME_PIN)
#error "Auto squared X-axis requires second home pin input"
#endif
#ifdef M4_LIMIT_PIN
#if X_AUTO_SQUARE
#define X2_LIMIT_PORT M4_LIMIT_PORT
@@ -136,6 +154,15 @@
#define X2_DIRECTION_PORT M5_DIRECTION_PORT
#define X2_DIRECTION_PIN M5_DIRECTION_PIN
#define X2_DIRECTION_BIT (1<<M5_DIRECTION_PIN)
#ifdef M5_HOME_PIN
#if X_AUTO_SQUARE
#define X2_HOME_PORT M5_HOME_PORT
#define X2_HOME_PIN M5_HOME_PIN
#define X2_HOME_BIT (1<<M5_HOME_PIN)
#endif
#elif X_AUTO_SQUARE && defined(X_HOME_PIN)
#error "Auto squared X-axis requires second home pin input"
#endif
#ifdef M5_LIMIT_PIN
#if X_AUTO_SQUARE
#define X2_LIMIT_PORT M5_LIMIT_PORT
@@ -171,6 +198,15 @@
#define X2_DIRECTION_PORT M6_DIRECTION_PORT
#define X2_DIRECTION_PIN M6_DIRECTION_PIN
#define X2_DIRECTION_BIT (1<<M6_DIRECTION_PIN)
#ifdef M6_HOME_PIN
#if X_AUTO_SQUARE
#define X2_HOME_PORT M6_HOME_PORT
#define X2_HOME_PIN M6_HOME_PIN
#define X2_HOME_BIT (1<<M6_HOME_PIN)
#endif
#elif X_AUTO_SQUARE && defined(X_HOME_PIN)
#error "Auto squared X-axis requires second home pin input"
#endif
#ifdef M6_LIMIT_PIN
#if X_AUTO_SQUARE
#define X2_LIMIT_PORT M6_LIMIT_PORT
@@ -206,6 +242,15 @@
#define X2_DIRECTION_PORT M7_DIRECTION_PORT
#define X2_DIRECTION_PIN M7_DIRECTION_PIN
#define X2_DIRECTION_BIT (1<<M7_DIRECTION_PIN)
#ifdef M7_HOME_PIN
#if X_AUTO_SQUARE
#define X2_HOME_PORT M7_HOME_PORT
#define X2_HOME_PIN M7_HOME_PIN
#define X2_HOME_BIT (1<<M7_HOME_PIN)
#endif
#elif X_AUTO_SQUARE && defined(X_HOME_PIN)
#error "Auto squared X-axis requires second home pin input"
#endif
#ifdef M7_LIMIT_PIN
#if X_AUTO_SQUARE
#define X2_LIMIT_PORT M7_LIMIT_PORT
@@ -243,6 +288,15 @@
#define Y2_DIRECTION_PORT M3_DIRECTION_PORT
#define Y2_DIRECTION_PIN M3_DIRECTION_PIN
#define Y2_DIRECTION_BIT (1<<M3_DIRECTION_PIN)
#ifdef M3_HOME_PIN
#if Y_AUTO_SQUARE
#define Y2_HOME_PORT M3_HOME_PORT
#define Y2_HOME_PIN M3_HOME_PIN
#define Y2_HOME_BIT (1<<M3_HOME_PIN)
#endif
#elif Y_AUTO_SQUARE && defined(Y_HOME_PIN)
#error "Auto squared Y-axis requires second home pin input"
#endif
#ifdef M3_LIMIT_PIN
#if Y_AUTO_SQUARE
#define Y2_LIMIT_PORT M3_LIMIT_PORT
@@ -278,6 +332,15 @@
#define Y2_DIRECTION_PORT M4_DIRECTION_PORT
#define Y2_DIRECTION_PIN M4_DIRECTION_PIN
#define Y2_DIRECTION_BIT (1<<M4_DIRECTION_PIN)
#ifdef M4_HOME_PIN
#if Y_AUTO_SQUARE
#define Y2_HOME_PORT M4_HOME_PORT
#define Y2_HOME_PIN M4_HOME_PIN
#define Y2_HOME_BIT (1<<M4_HOME_PIN)
#endif
#elif Y_AUTO_SQUARE && defined(Y_HOME_PIN)
#error "Auto squared Y-axis requires second home pin input"
#endif
#ifdef M4_LIMIT_PIN
#if Y_AUTO_SQUARE
#define Y2_LIMIT_PORT M4_LIMIT_PORT
@@ -313,6 +376,15 @@
#define Y2_DIRECTION_PORT M5_DIRECTION_PORT
#define Y2_DIRECTION_PIN M5_DIRECTION_PIN
#define Y2_DIRECTION_BIT (1<<M5_DIRECTION_PIN)
#ifdef M5_HOME_PIN
#if Y_AUTO_SQUARE
#define Y2_HOME_PORT M5_HOME_PORT
#define Y2_HOME_PIN M5_HOME_PIN
#define Y2_HOME_BIT (1<<M5_HOME_PIN)
#endif
#elif Y_AUTO_SQUARE && defined(Y_HOME_PIN)
#error "Auto squared Y-axis requires second home pin input"
#endif
#ifdef M5_LIMIT_PIN
#if Y_AUTO_SQUARE
#define Y2_LIMIT_PORT M5_LIMIT_PORT
@@ -348,6 +420,15 @@
#define Y2_DIRECTION_PORT M6_DIRECTION_PORT
#define Y2_DIRECTION_PIN M6_DIRECTION_PIN
#define Y2_DIRECTION_BIT (1<<M6_DIRECTION_PIN)
#ifdef M6_HOME_PIN
#if Y_AUTO_SQUARE
#define Y2_HOME_PORT M6_HOME_PORT
#define Y2_HOME_PIN M6_HOME_PIN
#define Y2_HOME_BIT (1<<M6_HOME_PIN)
#endif
#elif Y_AUTO_SQUARE && defined(Y_HOME_PIN)
#error "Auto squared Y-axis requires second home pin input"
#endif
#ifdef M6_LIMIT_PIN
#if Y_AUTO_SQUARE
#define Y2_LIMIT_PORT M6_LIMIT_PORT
@@ -383,6 +464,15 @@
#define Y2_DIRECTION_PORT M7_DIRECTION_PORT
#define Y2_DIRECTION_PIN M7_DIRECTION_PIN
#define Y2_DIRECTION_BIT (1<<M7_DIRECTION_PIN)
#ifdef M7_HOME_PIN
#if Y_AUTO_SQUARE
#define Y2_HOME_PORT M7_HOME_PORT
#define Y2_HOME_PIN M7_HOME_PIN
#define Y2_HOME_BIT (1<<M7_HOME_PIN)
#endif
#elif Y_AUTO_SQUARE && defined(Y_HOME_PIN)
#error "Auto squared Y-axis requires second home pin input"
#endif
#ifdef M7_LIMIT_PIN
#if Y_AUTO_SQUARE
#define Y2_LIMIT_PORT M7_LIMIT_PORT
@@ -420,6 +510,15 @@
#define Z2_DIRECTION_PORT M3_DIRECTION_PORT
#define Z2_DIRECTION_PIN M3_DIRECTION_PIN
#define Z2_DIRECTION_BIT (1<<M3_DIRECTION_PIN)
#ifdef M3_HOME_PIN
#if Z_AUTO_SQUARE
#define Z2_HOME_PORT M3_HOME_PORT
#define Z2_HOME_PIN M3_HOME_PIN
#define Z2_HOME_BIT (1<<M3_HOME_PIN)
#endif
#elif Z_AUTO_SQUARE && defined(Y_HOME_PIN)
#error "Auto squared Z-axis requires second home pin input"
#endif
#ifdef M3_LIMIT_PIN
#if Z_AUTO_SQUARE
#define Z2_LIMIT_PORT M3_LIMIT_PORT
@@ -455,6 +554,15 @@
#define Z2_DIRECTION_PORT M4_DIRECTION_PORT
#define Z2_DIRECTION_PIN M4_DIRECTION_PIN
#define Z2_DIRECTION_BIT (1<<M4_DIRECTION_PIN)
#ifdef M4_HOME_PIN
#if Z_AUTO_SQUARE
#define Z2_HOME_PORT M4_HOME_PORT
#define Z2_HOME_PIN M4_HOME_PIN
#define Z2_HOME_BIT (1<<M4_HOME_PIN)
#endif
#elif Z_AUTO_SQUARE && defined(Z_HOME_PIN)
#error "Auto squared Z-axis requires second home pin input"
#endif
#ifdef M4_LIMIT_PIN
#if Z_AUTO_SQUARE
#define Z2_LIMIT_PORT M4_LIMIT_PORT
@@ -490,6 +598,15 @@
#define Z2_DIRECTION_PORT M5_DIRECTION_PORT
#define Z2_DIRECTION_PIN M5_DIRECTION_PIN
#define Z2_DIRECTION_BIT (1<<M5_DIRECTION_PIN)
#ifdef M5_HOME_PIN
#if Z_AUTO_SQUARE
#define Z2_HOME_PORT M5_HOME_PORT
#define Z2_HOME_PIN M5_HOME_PIN
#define Z2_HOME_BIT (1<<M5_HOME_PIN)
#endif
#elif Z_AUTO_SQUARE && defined(Z_HOME_PIN)
#error "Auto squared Z-axis requires second home pin input"
#endif
#ifdef M5_LIMIT_PIN
#if Z_AUTO_SQUARE
#define Z2_LIMIT_PORT M5_LIMIT_PORT
@@ -525,6 +642,15 @@
#define Z2_DIRECTION_PORT M6_DIRECTION_PORT
#define Z2_DIRECTION_PIN M6_DIRECTION_PIN
#define Z2_DIRECTION_BIT (1<<M6_DIRECTION_PIN)
#ifdef M6_HOME_PIN
#if Z_AUTO_SQUARE
#define Z2_HOME_PORT M6_HOME_PORT
#define Z2_HOME_PIN M6_HOME_PIN
#define Z2_HOME_BIT (1<<M6_HOME_PIN)
#endif
#elif Z_AUTO_SQUARE && defined(Z_HOME_PIN)
#error "Auto squared Z-axis requires second home pin input"
#endif
#ifdef M6_LIMIT_PIN
#if Z_AUTO_SQUARE
#define Z2_LIMIT_PORT M6_LIMIT_PORT
@@ -560,6 +686,15 @@
#define Z2_DIRECTION_PORT M7_DIRECTION_PORT
#define Z2_DIRECTION_PIN M7_DIRECTION_PIN
#define Z2_DIRECTION_BIT (1<<M7_DIRECTION_PIN)
#ifdef M7_HOME_PIN
#if Z_AUTO_SQUARE
#define Z2_HOME_PORT M7_HOME_PORT
#define Z2_HOME_PIN M7_HOME_PIN
#define Z2_HOME_BIT (1<<M7_HOME_PIN)
#endif
#elif Z_AUTO_SQUARE && defined(Z_HOME_PIN)
#error "Auto squared Z-axis requires second home pin input"
#endif
#ifdef M7_LIMIT_PIN
#if Z_AUTO_SQUARE
#define Z2_LIMIT_PORT M7_LIMIT_PORT
@@ -597,6 +732,24 @@
#endif // N_GANGED
#if defined(X2_HOME_PIN) || defined(Y2_HOME_PIN) || defined(Z2_HOME_PIN)
#define DUAL_HOME_SWITCHES
#ifndef X2_HOME_BIT
#define X2_HOME_BIT 0
#endif
#ifndef Y2_HOME_BIT
#define Y2_HOME_BIT 0
#endif
#ifndef Z2_HOME_BIT
#define Z2_HOME_BIT 0
#endif
#define HOME2_MASK (X2_HOME_BIT|Y2_HOME_BIT|Z2_HOME_BIT)
#define HOME2_MASK_SUM (X2_HOME_BIT+Y2_HOME_BIT+Z2_HOME_BIT)
#else
#define HOME2_MASK 0
#define HOME2_MASK_SUM 0
#endif
#if defined(X2_LIMIT_PIN) || defined(Y2_LIMIT_PIN) || defined(Z2_LIMIT_PIN)
#define DUAL_LIMIT_SWITCHES
#ifndef X2_LIMIT_BIT
@@ -629,6 +782,11 @@
#define A_DIRECTION_PORT M3_DIRECTION_PORT
#define A_DIRECTION_PIN M3_DIRECTION_PIN
#define A_DIRECTION_BIT (1<<M3_DIRECTION_PIN)
#ifdef M3_HOME_PIN
#define A_HOME_PORT M3_HOME_PORT
#define A_HOME_PIN M3_HOME_PIN
#define A_HOME_BIT (1<<M3_HOME_PIN)
#endif
#ifdef M3_LIMIT_PIN
#define A_LIMIT_PORT M3_LIMIT_PORT
#define A_LIMIT_PIN M3_LIMIT_PIN
@@ -656,6 +814,11 @@
#define B_DIRECTION_PORT M4_DIRECTION_PORT
#define B_DIRECTION_PIN M4_DIRECTION_PIN
#define B_DIRECTION_BIT (1<<M4_DIRECTION_PIN)
#ifdef M4_HOME_PIN
#define B_HOME_PORT M4_HOME_PORT
#define B_HOME_PIN M4_HOME_PIN
#define B_HOME_BIT (1<<M4_HOME_PIN)
#endif
#ifdef M4_LIMIT_PIN
#define B_LIMIT_PORT M4_LIMIT_PORT
#define B_LIMIT_PIN M4_LIMIT_PIN
@@ -683,6 +846,11 @@
#define C_DIRECTION_PORT M5_DIRECTION_PORT
#define C_DIRECTION_PIN M5_DIRECTION_PIN
#define C_DIRECTION_BIT (1<<M5_DIRECTION_PIN)
#ifdef M5_HOME_PIN
#define C_HOME_PORT M5_HOME_PORT
#define C_HOME_PIN M5_HOME_PIN
#define C_HOME_BIT (1<<M5_HOME_PIN)
#endif
#ifdef M5_LIMIT_PIN
#define C_LIMIT_PORT M5_LIMIT_PORT
#define C_LIMIT_PIN M5_LIMIT_PIN
@@ -710,6 +878,11 @@
#define U_DIRECTION_PORT M6_DIRECTION_PORT
#define U_DIRECTION_PIN M6_DIRECTION_PIN
#define U_DIRECTION_BIT (1<<M6_DIRECTION_PIN)
#ifdef M6_HOME_PIN
#define U_HOME_PORT M6_HOME_PORT
#define U_HOME_PIN M6_HOME_PIN
#define U_HOME_BIT (1<<M6_HOME_PIN)
#endif
#ifdef M6_LIMIT_PIN
#define U_LIMIT_PORT M6_LIMIT_PORT
#define U_LIMIT_PIN M6_LIMIT_PIN
@@ -737,6 +910,11 @@
#define V_DIRECTION_PORT M7_DIRECTION_PORT
#define V_DIRECTION_PIN M7_DIRECTION_PIN
#define V_DIRECTION_BIT (1<<M7_DIRECTION_PIN)
#ifdef M7_HOME_PIN
#define V_HOME_PORT M7_HOME_PORT
#define V_HOME_PIN M7_HOME_PIN
#define V_HOME_BIT (1<<M7_HOME_PIN)
#endif
#ifdef M7_LIMIT_PIN
#define V_LIMIT_PORT M7_LIMIT_PORT
#define V_LIMIT_PIN M7_LIMIT_PIN
@@ -856,6 +1034,28 @@
#endif
#endif
#ifndef X_HOME_BIT
#ifdef X_HOME_PIN
#define X_HOME_BIT (1<<X_HOME_PIN)
#else
#define X_HOME_BIT 0
#endif
#endif
#ifndef Y_HOME_BIT
#ifdef Y_HOME_PIN
#define Y_HOME_BIT (1<<Y_HOME_PIN)
#else
#define Y_HOME_BIT 0
#endif
#endif
#ifndef Z_HOME_BIT
#ifdef Z_HOME_PIN
#define Z_HOME_BIT (1<<Z_HOME_PIN)
#else
#define Z_HOME_BIT 0
#endif
#endif
#ifndef X_LIMIT_BIT
#define X_LIMIT_BIT (1<<X_LIMIT_PIN)
#endif
@@ -964,7 +1164,35 @@
#endif
#endif
#endif // STEPPERS_ENABLE_MASK
#endif // STEPPERS_ENABLE_MASK
#ifndef HOME_MASK
#define HOME_MASK_BASE (X_HOME_BIT|Y_HOME_BIT|Z_HOME_BIT|HOME2_MASK)
#define HOME_MASK_BASE_SUM (X_HOME_BIT+Y_HOME_BIT+Z_HOME_BIT+HOME2_MASK_SUM)
#if N_AXIS == 3
#define HOME_MASK HOME_MASK_BASE
#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)
#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)
#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)
#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)
#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)
#endif
#endif // HOME_MASK
#ifndef LIMIT_MASK
@@ -1008,8 +1236,8 @@
#define LIMIT_MASK_BASE (X_LIMIT_BIT|Y_LIMIT_BIT|LIMIT2_MASK)
#define LIMIT_MASK_BASE_SUM (X_LIMIT_BIT+Y_LIMIT_BIT+LIMIT2_MASK_SUM)
#else
#define LIMIT_MASK_BASE (X_LIMIT_BIT|Y_LIMIT_BIT|Z_LIMIT_BIT|X_LIMIT_BIT_MAX|Y_LIMIT_BIT_MAX|Z_LIMIT_BIT_MAX)
#define LIMIT_MASK_BASE_SUM (X_LIMIT_BIT+Y_LIMIT_BIT+Z_LIMIT_BIT+X_LIMIT_BIT_MAX+Y_LIMIT_BIT_MAX+Z_LIMIT_BIT_MAX)
#define LIMIT_MASK_BASE (X_LIMIT_BIT|Y_LIMIT_BIT|Z_LIMIT_BIT|X_LIMIT_BIT_MAX|Y_LIMIT_BIT_MAX|Z_LIMIT_BIT_MAX|LIMIT2_MASK)
#define LIMIT_MASK_BASE_SUM (X_LIMIT_BIT+Y_LIMIT_BIT+Z_LIMIT_BIT+X_LIMIT_BIT_MAX+Y_LIMIT_BIT_MAX+Z_LIMIT_BIT_MAX+LIMIT2_MASK_SUM)
#endif
#if N_AXIS == 3
@@ -1035,10 +1263,6 @@
#endif // LIMIT_MASK
#ifndef HOME_MASK
#define HOME_MASK 0
#endif
#ifndef N_GANGED
#define N_GANGED 0
#endif
@@ -1072,7 +1296,7 @@ static void motor_iterator (motor_iterator_callback_ptr callback)
}
}
static limit_signals_t get_limits_cap (void)
static inline limit_signals_t get_limits_cap (void)
{
limit_signals_t limits = {0};
@@ -1139,45 +1363,45 @@ static limit_signals_t get_limits_cap (void)
return limits;
}
static home_signals_t get_home_cap (void)
static inline home_signals_t get_home_cap (void)
{
home_signals_t home = {0};
#if HOME_MASK
#if X_HOME_BIT
home.primary.x = On;
home.a.x = On;
#endif
#if Y_HOME_BIT
home.primary.y = On;
home.a.y = On;
#endif
#if Z_HOME_BIT
home.primary.z = On;
home.a.z = On;
#endif
#if A_HOME_BIT
home.primary.a = On;
home.a.a = On;
#endif
#if B_HOME_BIT
home.primary.b = On;
home.a.b = On;
#endif
#if C_HOME_BIT
home.primary.c = On;
home.a.c = On;
#endif
#if U_HOME_BIT
home.primary.u = On;
home.a.u = On;
#endif
#if V_HOME_BIT
home.primary.v = On;
home.a.v = On;
#endif
#if X2_HOME_BIT
home.secondary.x = On;
home.b.x = On;
#endif
#if Y2_HOME_BIT
home.secondary.y = On;
home.b.y = On;
#endif
#if Z2_HOME_BIT
home.secondary.z = On;
home.b.z = On;
#endif
#endif // HOME_MASK
+30 -15
View File
@@ -339,8 +339,8 @@ typedef bool (*aux_claim_explicit_ptr)(aux_ctrl_t *aux_ctrl);
static bool aux_ctrl_claim_port (xbar_t *properties, uint8_t port, void *data)
{
if(ioport_claim(Port_Digital, Port_Input, &properties->id, xbar_fn_to_pinname(((aux_ctrl_t *)data)->function)))
((aux_ctrl_t *)data)->aux_port = properties->id;
if(ioport_claim(Port_Digital, Port_Input, &port, xbar_fn_to_pinname(((aux_ctrl_t *)data)->function)))
((aux_ctrl_t *)data)->aux_port = port;
return ((aux_ctrl_t *)data)->aux_port != 0xFF;
}
@@ -396,15 +396,24 @@ static inline control_signals_t aux_ctrl_scan_status (control_signals_t signals)
// The following pins are bound explicitly to aux output pins
static aux_ctrl_out_t aux_ctrl_out[] = {
#ifdef DRIVER_SPINDLE_ENABLE
{ .function = Output_SpindleOn, .aux_port = 0xFF, .pin = SPINDLE_ENABLE_PIN, .port = SPINDLE_ENABLE_PORT },
#if DRIVER_SPINDLE_ENABLE
{ .function = Output_SpindleOn, .aux_port = 0xFF, .pin = SPINDLE_ENABLE_PIN, .port = SPINDLE_ENABLE_PORT },
#if DRIVER_SPINDLE_PWM_ENABLE
{ .function = Output_SpindlePWM, .aux_port = 0xFF, .pin = SPINDLE_PWM_PIN, .port = SPINDLE_PWM_PORT },
#endif
#ifdef DRIVER_SPINDLE_PWM_ENABLE
{ .function = Output_SpindlePWM, .aux_port = 0xFF, .pin = SPINDLE_PWM_PIN, .port = SPINDLE_PWM_PORT },
#if DRIVER_SPINDLE_DIR_ENABLE
{ .function = Output_SpindleDir, .aux_port = 0xFF, .pin = SPINDLE_DIRECTION_PIN, .port = SPINDLE_DIRECTION_PORT },
#endif
#ifdef DRIVER_SPINDLE_DIR_ENABLE
{ .function = Output_SpindleDir, .aux_port = 0xFF, .pin = SPINDLE_DIRECTION_PIN, .port = SPINDLE_DIRECTION_PORT },
#endif // DRIVER_SPINDLE_ENABLE
#if DRIVER_SPINDLE1_ENABLE
{ .function = Output_Spindle1On, .aux_port = 0xFF, .pin = SPINDLE1_ENABLE_PIN, .port = SPINDLE1_ENABLE_PORT },
#if DRIVER_SPINDLE1_PWM_ENABLE
{ .function = Output_Spindle1PWM, .aux_port = 0xFF, .pin = SPINDLE1_PWM_PIN, .port = SPINDLE1_PWM_PORT },
#endif
#if DRIVER_SPINDLE1_DIR_ENABLE
{ .function = Output_Spindle1Dir, .aux_port = 0xFF, .pin = SPINDLE1_DIRECTION_PIN, .port = SPINDLE1_DIRECTION_PORT },
#endif
#endif // DRIVER_SPINDLE1_DIR_ENABLE
/*
#ifdef COOLANT_FLOOD_PIN
{ .function = Output_CoolantFlood, .aux_port = 0xFF, .pin = COOLANT_FLOOD_PIN, .port = COOLANT_FLOOD_PORT },
@@ -421,7 +430,7 @@ static inline aux_ctrl_out_t *aux_out_remap_explicit (void *port, uint8_t pin, u
uint_fast8_t idx = sizeof(aux_ctrl_out) / sizeof(aux_ctrl_out_t);
do {
if(idx) do {
idx--;
if(aux_ctrl_out[idx].port == port && aux_ctrl_out[idx].pin == pin) {
ctrl_pin = &aux_ctrl_out[idx];
@@ -437,8 +446,8 @@ typedef bool (*aux_claim_explicit_out_ptr)(aux_ctrl_out_t *aux_ctrl);
static bool aux_ctrl_claim_out_port (xbar_t *properties, uint8_t port, void *data)
{
if(ioport_claim(Port_Digital, Port_Output, &properties->id, xbar_fn_to_pinname(((aux_ctrl_t *)data)->function)))
((aux_ctrl_t *)data)->aux_port = properties->id;
if(ioport_claim(Port_Digital, Port_Output, &port, xbar_fn_to_pinname(((aux_ctrl_t *)data)->function)))
((aux_ctrl_t *)data)->aux_port = port;
return ((aux_ctrl_t *)data)->aux_port != 0xFF;
}
@@ -451,10 +460,9 @@ static inline void aux_ctrl_claim_out_ports (aux_claim_explicit_out_ptr aux_clai
aux_claim = aux_ctrl_claim_out_port;
for(idx = 0; idx < sizeof(aux_ctrl_out) / sizeof(aux_ctrl_out_t); idx++) {
if(aux_ctrl_out[idx].pin == 0xFF) {
if(ioports_enumerate(Port_Digital, Port_Output, (pin_cap_t){ .claimable = On }, aux_claim, (void *)&aux_ctrl_out[idx]))
hal.signals_cap.mask |= aux_ctrl[idx].cap.mask;
} else if(aux_ctrl_out[idx].aux_port != 0xFF)
if(aux_ctrl_out[idx].pin == 0xFF)
ioports_enumerate(Port_Digital, Port_Output, (pin_cap_t){ .claimable = On }, aux_claim, (void *)&aux_ctrl_out[idx]);
else if(aux_ctrl_out[idx].aux_port != 0xFF)
aux_claim_explicit(&aux_ctrl_out[idx]);
}
}
@@ -482,6 +490,13 @@ static inline void aux_ctrl_claim_out_ports (aux_claim_explicit_out_ptr aux_clai
#define SPINDLE_DIRECTION_BIT (1<<SPINDLE_DIRECTION_PIN)
#endif
#if defined(SPINDLE1_ENABLE_PIN) && !defined(SPINDLE1_ENABLE_BIT)
#define SPINDLE1_ENABLE_BIT (1<<SPINDLE1_ENABLE_PIN)
#endif
#if defined(SPINDLE1_DIRECTION_PIN) && !defined(SPINDLE1_DIRECTION_BIT)
#define SPINDLE1_DIRECTION_BIT (1<<SPINDLE1_DIRECTION_PIN)
#endif
#if defined(COOLANT_FLOOD_PIN) && !defined(COOLANT_FLOOD_BIT)
#define COOLANT_FLOOD_BIT (1<<COOLANT_FLOOD_PIN)
#endif
+7 -6
View File
@@ -3,25 +3,26 @@
Part of grblHAL
Copyright (c) 2021 Terje Io
Copyright (c) 2021-2024 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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#if defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F407xx) || defined(STM32F411xE) || defined(STM32F446xx) || defined(STM32F756xx) || defined(STM32H743xx) || defined(STM32H723xx)
#if defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F407xx) || defined(STM32F411xE) || \
defined(STM32F412Vx) || defined(STM32F446xx) || defined(STM32F756xx) || defined(STM32H743xx) || defined(STM32H723xx)
#define STM32_PLATFORM
#endif
+10 -1
View File
@@ -825,10 +825,11 @@ void report_build_info (char *line, bool extended)
// Generate compile-time build option list
char *append = &buf[5];
spindle_ptrs_t *spindle = spindle_get(0);
strcpy(buf, "[OPT:");
if(spindle_get_caps(false).variable)
if(spindle && spindle->cap.variable)
*append++ = 'V';
*append++ = 'N';
@@ -855,6 +856,9 @@ void report_build_info (char *line, bool extended)
if(settings.probe.allow_feed_override)
*append++ = 'A';
if(spindle && !spindle->cap.direction) // NOTE: Shown when disabled.
*append++ = 'D';
if(settings.spindle.flags.enable_rpm_controlled)
*append++ = '0';
@@ -1226,6 +1230,9 @@ void report_realtime_status (void)
}
}
#elif N_SPINDLE > 1
if(report.spindle_id)
hal.stream.write_all(appendbuf(2, "|S:", uitoa((uint32_t)spindle_0->id)));
#endif
if(settings.status_report.pin_state) {
@@ -2446,6 +2453,8 @@ static void report_spindle (spindle_info_t *spindle, void *data)
*caps++ = 'D';
if(spindle->hal->cap.laser)
*caps++ = 'L';
if(spindle->hal->cap.laser && spindle->hal->pulse_on)
*caps++ = 'A';
if(spindle->hal->cap.pid)
*caps++ = 'P';
if(spindle->hal->cap.pwm_invert)
+10
View File
@@ -80,6 +80,16 @@ typedef struct {
uint8_t intensity;
} neopixel_cfg_t;
static inline bool rgb_is_neopixels (rgb_ptr_t *device)
{
return device->out != NULL && device->cap.R > 126 && device->cap.G > 126 && device->cap.B > 126;
}
static inline bool rgb_is_onoff (rgb_ptr_t *device)
{
return device->out != NULL && device->cap.R == 1 && device->cap.G == 1 && device->cap.B == 1;
}
// Intensity conversions
static inline rgb_color_t rgb_set_intensity (rgb_color_t color, uint8_t intensity)
+63 -25
View File
@@ -113,6 +113,7 @@ PROGMEM const settings_t defaults = {
.homing.flags.manual = DEFAULT_HOMING_ALLOW_MANUAL,
.homing.flags.override_locks = DEFAULT_HOMING_OVERRIDE_LOCKS,
.homing.flags.keep_on_reset = DEFAULT_HOMING_KEEP_STATUS_ON_RESET,
.homing.flags.use_limit_switches = DEFAULT_HOMING_USE_LIMIT_SWITCHES,
#else
.homing.flags.value = 0,
#endif
@@ -128,6 +129,7 @@ PROGMEM const settings_t defaults = {
.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,
.home_invert.mask = DEFAULT_HOME_SIGNALS_INVERT_MASK,
.status_report.machine_position = DEFAULT_REPORT_MACHINE_POSITION,
.status_report.buffer_state = DEFAULT_REPORT_BUFFER_STATE,
@@ -425,6 +427,9 @@ static status_code_t set_ngc_debug_out (setting_id_t id, uint_fast16_t int_value
#endif
static bool machine_mode_changed = false;
#if COMPATIBILITY_LEVEL <= 1
static char homing_options[] = "Enable,Enable single axis commands,Homing on startup required,Set machine origin to 0,Two switches shares one input pin,Allow manual,Override locks,Keep homed status on reset,Use limit switches";
#endif
static char control_signals[] = "Reset,Feed hold,Cycle start,Safety door,Block delete,Optional stop,EStop,Probe connected,Motor fault,Motor warning,Limits override,Single step blocks";
static char spindle_signals[] = "Spindle enable,Spindle direction,PWM";
static char coolant_signals[] = "Flood,Mist";
@@ -459,7 +464,7 @@ PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_InvertProbePin, Group_Probing, "Invert probe pin", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_probe_invert, get_int, is_setting_available },
{ Setting_SpindlePWMBehaviour, Group_Spindle, "Deprecated", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_pwm_mode, get_int, is_setting_available },
{ Setting_GangedDirInvertMask, Group_Stepper, "Ganged axes direction invert", NULL, Format_Bitfield, ganged_axes, NULL, NULL, Setting_IsExtendedFn, set_ganged_dir_invert, get_int, is_setting_available },
{ Setting_SpindlePWMOptions, Group_Spindle, "PWM Spindle", NULL, Format_XBitfield, "Enable,RPM controls spindle enable signal", NULL, NULL, Setting_IsExtendedFn, set_pwm_options, get_int, is_setting_available },
{ Setting_SpindlePWMOptions, Group_Spindle, "PWM Spindle", NULL, Format_XBitfield, "Enable,RPM controls spindle enable signal,Disable laser mode capability", NULL, NULL, Setting_IsExtendedFn, set_pwm_options, get_int, is_setting_available },
#if COMPATIBILITY_LEVEL <= 1
{ Setting_StatusReportMask, Group_General, "Status report options", NULL, Format_Bitfield, "Position in machine coordinate,Buffer state,Line numbers,Feed & speed,Pin state,Work coordinate offset,Overrides,Probe coordinates,Buffer sync on WCO change,Parser state,Alarm substatus,Run substatus", NULL, NULL, Setting_IsExtendedFn, set_report_mask, get_int, NULL },
#else
@@ -485,7 +490,7 @@ PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_HardLimitsEnable, Group_Limits, "Hard limits enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_hard_limits_enable, get_int, NULL },
#endif
#if COMPATIBILITY_LEVEL <= 1
{ Setting_HomingEnable, Group_Homing, "Homing cycle", NULL, Format_XBitfield, "Enable,Enable single axis commands,Homing on startup required,Set machine origin to 0,Two switches shares one input pin,Allow manual,Override locks,Keep homed status on reset", NULL, NULL, Setting_IsExpandedFn, set_homing_enable, get_int, NULL },
{ Setting_HomingEnable, Group_Homing, "Homing cycle", NULL, Format_XBitfield, homing_options, NULL, NULL, Setting_IsExpandedFn, set_homing_enable, get_int, NULL },
#else
{ Setting_HomingEnable, Group_Homing, "Homing cycle enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_homing_enable, get_int, NULL },
#endif
@@ -618,7 +623,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_IsExtendedFn, set_offset_lock, get_int, 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_FSOptions, Group_General, "File systems options", NULL, Format_Bitfield, fs_options, NULL, NULL, Setting_IsExtended, &settings.fs_options.mask, NULL, is_setting_available }
{ Setting_FSOptions, Group_General, "File systems options", NULL, Format_Bitfield, fs_options, NULL, NULL, Setting_IsExtended, &settings.fs_options.mask, NULL, is_setting_available },
{ Setting_HomePinsInvertMask, Group_Limits, "Invert home pins", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.home_invert.mask, NULL, is_setting_available },
};
#ifndef NO_SETTINGS_DESCRIPTIONS
@@ -795,7 +801,8 @@ PROGMEM static const setting_descr_t setting_descr[] = {
{ Setting_NGCDebugOut, "Example: (debug, metric mode: #<_metric>, coord system: #5220)" },
#endif
{ Setting_EncoderSpindle, "Specifies which spindle has the encoder attached." },
{ Setting_FSOptions, "Auto mount SD card on startup." }
{ Setting_FSOptions, "Auto mount SD card on startup." },
{ Setting_HomePinsInvertMask, "Inverts the axis home input signals." },
};
#endif
@@ -993,14 +1000,15 @@ static status_code_t set_pwm_mode (setting_id_t id, uint_fast16_t int_value)
static status_code_t set_pwm_options (setting_id_t id, uint_fast16_t int_value)
{
if(int_value & 0x01) {
if(int_value > 0b11)
if(int_value & 0x001) {
if(int_value > 0b111)
return Status_SettingValueOutOfRange;
settings.spindle.flags.pwm_disable = Off;
settings.spindle.flags.enable_rpm_controlled = (int_value & 0b10) >> 1;
settings.spindle.flags.enable_rpm_controlled = !!(int_value & 0b010);
settings.spindle.flags.laser_mode_disable = !!(int_value & 0b100);
} else {
settings.spindle.flags.pwm_disable = On;
settings.spindle.flags.enable_rpm_controlled = Off;
settings.spindle.flags.enable_rpm_controlled = settings.spindle.flags.laser_mode_disable = Off;
}
return Status_OK;
@@ -1045,7 +1053,7 @@ static status_code_t set_spindle_invert (setting_id_t id, uint_fast16_t int_valu
static status_code_t set_control_disable_pullup (setting_id_t id, uint_fast16_t int_value)
{
settings.control_disable_pullup.mask = int_value & hal.signals_cap.mask;
settings.control_disable_pullup.mask = int_value & (hal.signals_cap.mask & ~limits_override.mask);
ioport_setting_changed(id);
@@ -1151,7 +1159,11 @@ static status_code_t set_jog_soft_limited (setting_id_t id, uint_fast16_t int_va
static status_code_t set_homing_enable (setting_id_t id, uint_fast16_t int_value)
{
if (bit_istrue(int_value, bit(0))) {
homing_flags_t homing;
homing.value = int_value;
if(homing.enabled) {
#if COMPATIBILITY_LEVEL > 1
settings.homing.flags.enabled = On;
settings.homing.flags.init_lock = DEFAULT_HOMING_INIT_LOCK;
@@ -1160,13 +1172,15 @@ static status_code_t set_homing_enable (setting_id_t id, uint_fast16_t int_value
settings.homing.flags.manual = DEFAULT_HOMING_ALLOW_MANUAL;
settings.homing.flags.override_locks = DEFAULT_HOMING_OVERRIDE_LOCKS;
settings.homing.flags.keep_on_reset = DEFAULT_HOMING_KEEP_STATUS_ON_RESET;
settings.homing.flags.use_limit_switches = DEFAULT_HOMING_USE_LIMIT_SWITCHES;
settings.limits.flags.two_switches = DEFAULT_LIMITS_TWO_SWITCHES_ON_AXES;
#else
settings.homing.flags.value = int_value & 0x0F;
settings.limits.flags.two_switches = bit_istrue(int_value, bit(4));
settings.homing.flags.manual = bit_istrue(int_value, bit(5));
settings.homing.flags.override_locks = bit_istrue(int_value, bit(6));
settings.homing.flags.keep_on_reset = bit_istrue(int_value, bit(7));
settings.homing.flags.value = int_value & 0b111;
settings.limits.flags.two_switches = homing.two_switches;
settings.homing.flags.manual = homing.manual;
settings.homing.flags.override_locks = homing.override_locks;
settings.homing.flags.keep_on_reset = homing.keep_on_reset;
settings.homing.flags.use_limit_switches = homing.use_limit_switches;
#endif
} else {
settings.homing.flags.value = 0;
@@ -1575,7 +1589,9 @@ static uint32_t get_int (setting_id_t id)
#endif
case Setting_SpindlePWMOptions:
value = settings.spindle.flags.pwm_disable ? 0 : (settings.spindle.flags.enable_rpm_controlled ? 0b11 : 0b01);
value = settings.spindle.flags.pwm_disable ? 0 : (0b001 |
(settings.spindle.flags.enable_rpm_controlled ? 0b010 : 0) |
(settings.spindle.flags.laser_mode_disable ? 0b100 : 0));
break;
case Setting_Mode:
@@ -1603,7 +1619,7 @@ static uint32_t get_int (setting_id_t id)
break;
case Setting_ControlInvertMask:
value = (settings.control_invert.mask & hal.signals_cap.mask) & ~limits_override.mask;
value = settings.control_invert.mask & (hal.signals_cap.mask & ~limits_override.mask);
break;
case Setting_SpindleInvertMask:
@@ -1611,7 +1627,7 @@ static uint32_t get_int (setting_id_t id)
break;
case Setting_ControlPullUpDisableMask:
value = settings.control_disable_pullup.mask & hal.signals_cap.mask;
value = settings.control_disable_pullup.mask;
break;
case Setting_ProbePullUpDisable:
@@ -1632,12 +1648,19 @@ static uint32_t get_int (setting_id_t id)
value = settings.limits.flags.jog_soft_limited;
break;
case Setting_HomingEnable:
value = (settings.homing.flags.value & 0x0F) |
(settings.limits.flags.two_switches ? bit(4) : 0) |
(settings.homing.flags.manual ? bit(5) : 0) |
(settings.homing.flags.override_locks ? bit(6) : 0) |
(settings.homing.flags.keep_on_reset ? bit(7) : 0);
case Setting_HomingEnable:;
#if COMPATIBILITY_LEVEL <= 1
homing_flags_t homing;
homing.value = settings.homing.flags.value & 0b1111;
homing.two_switches = settings.limits.flags.two_switches;
homing.manual = settings.homing.flags.manual;
homing.override_locks = settings.homing.flags.override_locks;
homing.keep_on_reset = settings.homing.flags.keep_on_reset;
homing.use_limit_switches = settings.homing.flags.use_limit_switches;
value = homing.value;
#else
value = settings.homing.flags.enable;
#endif
break;
case Setting_StepperDeenergizeMask:
@@ -2010,6 +2033,10 @@ static bool is_setting_available (const setting_detail_t *setting)
available = hal.driver_cap.sd_card || hal.driver_cap.littlefs;
break;
case Setting_HomePinsInvertMask:
available = hal.homing.get_state != NULL && hal.home_cap.a.mask != 0;
break;
default:
break;
}
@@ -2167,6 +2194,7 @@ bool read_global_settings ()
#endif
settings.control_invert.mask |= limits_override.mask;
settings.control_disable_pullup.mask &= ~limits_override.mask;
return ok && settings.version == SETTINGS_VERSION;
}
@@ -2201,6 +2229,7 @@ void settings_restore (settings_restore_t restore)
memcpy(&settings, &defaults, sizeof(settings_t));
settings.control_invert.mask = (settings.control_invert.mask & hal.signals_cap.mask) | limits_override.mask;
settings.control_disable_pullup.mask &= (hal.signals_cap.mask & ~limits_override.mask);
settings.spindle.invert.ccw &= spindle_get_caps(false).direction;
settings.spindle.invert.pwm &= spindle_get_caps(false).pwm_invert;
#if ENABLE_BACKLASH_COMPENSATION
@@ -2929,7 +2958,7 @@ void settings_init (void)
setting_remove_elements(Setting_SpindleInvertMask, spindle_state.mask);
}
setting_remove_elements(Setting_ControlInvertMask, hal.signals_cap.mask);
setting_remove_elements(Setting_ControlInvertMask, hal.signals_cap.mask & ~limits_override.mask);
if(hal.stepper.get_ganged)
setting_remove_elements(Setting_GangedDirInvertMask, hal.stepper.get_ganged(false).mask);
@@ -2937,6 +2966,15 @@ void settings_init (void)
if(!hal.driver_cap.mist_control)
setting_remove_element(Setting_CoolantInvertMask, 1);
#if COMPATIBILITY_LEVEL <= 1
if(hal.homing.get_state == NULL) {
homing_flags_t homing;
homing.value = -1;
homing.use_limit_switches = Off;
setting_remove_elements(Setting_HomingEnable, homing.value);
}
#endif
setting_details_t *details = setting_details.next;
if(details) do {
+46 -2
View File
@@ -410,6 +410,32 @@ typedef enum {
Setting_FSOptions = 650,
Setting_Stepper1 = 651,
Setting_Stepper2 = 652,
Setting_Stepper3 = 653,
Setting_Stepper4 = 654,
Setting_Stepper5 = 655,
Setting_Stepper6 = 656,
Setting_Stepper7 = 657,
Setting_Stepper8 = 658,
Setting_Stepper9 = 659,
Setting_Stepper10 = 660,
Setting_Stepper11 = 661,
Setting_Stepper12 = 662,
Setting_Stepper13 = 663,
Setting_Stepper14 = 664,
Setting_Stepper15 = 665,
Setting_Stepper16 = 666,
Setting_Stepper17 = 667,
Setting_Stepper18 = 668,
Setting_Stepper19 = 669,
Setting_Stepper20 = 670,
Setting_HomePinsInvertMask = 671,
Setting_Reserved672 = 672,
Setting_SpindleInvertMask1 = 716,
Setting_RpmMax1 = 730,
Setting_RpmMin1 = 731,
Setting_Mode1 = 732,
@@ -576,10 +602,28 @@ typedef union {
manual :1,
override_locks :1,
keep_on_reset :1,
unassigned :1;
use_limit_switches :1;
};
} homing_settings_flags_t;
// Used internally in settings.c only.
// TODO: replace homing_settings_flags_t with this on a settings struct revision?
typedef union {
uint16_t value;
struct {
uint16_t enabled :1,
single_axis_commands :1,
init_lock :1,
force_set_origin :1,
two_switches :1, // is a limits setting
manual :1,
override_locks :1,
keep_on_reset :1,
use_limit_switches :1,
unused :7;
};
} homing_flags_t;
typedef struct {
float fail_length_percent; // DEFAULT_DUAL_AXIS_HOMING_FAIL_AXIS_LENGTH_PERCENT
float fail_distance_max; // DEFAULT_DUAL_AXIS_HOMING_FAIL_DISTANCE_MAX
@@ -719,7 +763,7 @@ typedef struct {
control_signals_t control_invert;
control_signals_t control_disable_pullup;
coolant_state_t coolant_invert;
uint8_t hole_0;
axes_signals_t home_invert;
uint16_t hole_1;
spindle_settings_t spindle;
stepper_settings_t steppers;
+328 -5
View File
@@ -7,18 +7,18 @@
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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
@@ -51,6 +51,7 @@ typedef struct {
static uint8_t n_spindle = 0;
static spindle_sys_t sys_spindle[N_SYS_SPINDLE] = {0};
static spindle_reg_t spindles[N_SPINDLE] = {0}, *pwm_spindle = NULL;
static spindle_cap_t spindle_cap;
/*! \internal \brief Activates and registers a spindle as enabled with a specific spindle number.
\param spindle_id spindle id of spindle to activate as a \ref spindle_id_t.
@@ -124,6 +125,9 @@ static bool spindle_activate (spindle_id_t spindle_id, spindle_num_t spindle_num
memcpy(&sys_spindle[spindle_num].hal, &spindle_hal, sizeof(spindle_ptrs_t));
if(grbl.on_spindle_selected)
grbl.on_spindle_selected(&sys_spindle[spindle_num].hal);
#if N_SPINDLE > 1
system_add_rt_report(Report_SpindleId);
#endif
}
}
}
@@ -273,7 +277,7 @@ void spindle_update_caps (spindle_ptrs_t *spindle, spindle_pwm_t *pwm_caps)
uint_fast8_t idx = N_SYS_SPINDLE;
spindle->type = pwm_caps ? SpindleType_PWM : SpindleType_Basic;
spindle->cap.laser = !!pwm_caps && !!spindle->update_pwm && settings.mode == Mode_Laser;
spindle->cap.laser = !!pwm_caps && !pwm_caps->flags.laser_mode_disable && !!spindle->update_pwm && settings.mode == Mode_Laser;
spindle->pwm_off_value = pwm_caps ? pwm_caps->off_value : 0;
do {
@@ -767,6 +771,10 @@ bool spindle_precompute_pwm_values (spindle_ptrs_t *spindle, spindle_pwm_t *pwm_
pwm_data->compute_value = compute_dummy_pwm_value;
}
pwm_data->flags.invert_pwm = pwm_data->invert_pwm;
pwm_data->flags.always_on = pwm_data->always_on;
pwm_data->flags.cloned = pwm_data->cloned;
spindle->context.pwm = pwm_data;
#if ENABLE_SPINDLE_LINEARIZATION
@@ -784,3 +792,318 @@ bool spindle_precompute_pwm_values (spindle_ptrs_t *spindle, spindle_pwm_t *pwm_
return spindle->cap.variable;
}
#if N_SPINDLE > 1
#include "grbl/nvs_buffer.h"
static spindle1_settings_t sp1_settings;
static uint32_t nvs_address;
static char spindle_signals[] = "Spindle enable,Spindle direction,PWM";
static spindle1_settings_changed_ptr on_settings_changed;
static bool ports_ok = false;
static char max_aport[4], max_dport[4];
#if ENABLE_SPINDLE_LINEARIZATION
static status_code_t set_linear_piece (setting_id_t id, char *svalue)
{
uint32_t idx = id - Setting_LinearSpindle1Piece1;
float rpm, start, end;
if(*svalue == '\0' || (svalue[0] == '0' && svalue[1] == '\0')) {
sp1_settings.cfg.pwm_piece[idx].rpm = NAN;
sp1_settings.cfg.pwm_piece[idx].start =
sp1_settings.cfg.pwm_piece[idx].end = 0.0f;
} else if(sscanf(svalue, "%f,%f,%f", &rpm, &start, &end) == 3) {
sp1_settings.cfg.pwm_piece[idx].rpm = rpm;
sp1_settings.cfg.pwm_piece[idx].start = start;
sp1_settings.cfg.pwm_piece[idx].end = end;
//?? if(idx == 0)
// sp1_settings.cfg.rpm_min = rpm;
} else
return Status_SettingValueOutOfRange;
return Status_OK;
}
static char *get_linear_piece (setting_id_t id)
{
static char buf[40];
uint32_t idx = id - Setting_LinearSpindle1Piece1;
if(isnan(sp1_settings.cfg.pwm_piece[idx].rpm))
*buf = '\0';
else
snprintf(buf, sizeof(buf), "%g,%g,%g", sp1_settings.cfg.pwm_piece[idx].rpm, sp1_settings.cfg.pwm_piece[idx].start, sp1_settings.cfg.pwm_piece[idx].end);
return buf;
}
#endif
static status_code_t set_spindle_invert (setting_id_t id, uint_fast16_t int_value)
{
sp1_settings.cfg.invert.mask = int_value;
if(sp1_settings.cfg.invert.pwm && !spindle_cap.pwm_invert) {
sp1_settings.cfg.invert.pwm = Off;
return Status_SettingDisabled;
}
return Status_OK;
}
static uint32_t get_int (setting_id_t id)
{
uint32_t value = 0;
switch(id) {
case Setting_SpindleInvertMask1:
value = sp1_settings.cfg.invert.value;
break;
default:
break;
}
return value;
}
static status_code_t set_dir_port (setting_id_t id, float value)
{
sp1_settings.port_dir = value < 0.0f ? 255 : (int8_t)value;
return Status_OK;
}
static float get_dir_port (setting_id_t id)
{
return sp1_settings.port_dir == 255 ? -1.0f : (float)sp1_settings.port_dir;
}
static uint32_t get_pwm_port (setting_id_t id)
{
return (uint32_t)sp1_settings.port_pwm;
}
bool pwm_port_validate (xbar_t *properties, uint8_t port, void *data)
{
return port == (uint8_t)((uint32_t)data);
}
static status_code_t set_pwm_port (setting_id_t id, uint_fast16_t int_value)
{
bool ok;
if((ok = (uint8_t)int_value == sp1_settings.port_pwm ||
ioports_enumerate(Port_Analog, Port_Output, (pin_cap_t){ .pwm = On, .claimable = On }, pwm_port_validate, (void *)((uint32_t)int_value))))
sp1_settings.port_pwm = (uint8_t)int_value;
return ok ? Status_OK : Status_SettingValueOutOfRange;
}
static bool has_pwm (const setting_detail_t *setting)
{
return spindle_cap.variable;
}
static bool has_freq (const setting_detail_t *setting)
{
return spindle_cap.variable && !spindle_cap.cloned;
}
static bool has_ports (const setting_detail_t *setting)
{
return ports_ok;
}
static const setting_detail_t spindle1_settings[] = {
{ Setting_Spindle_OnPort, Group_AuxPorts, "PWM2 spindle on port", NULL, Format_Int8, "##0", "0", max_dport, Setting_NonCore, &sp1_settings.port_on, NULL, has_ports, { .reboot_required = On } },
{ Setting_Spindle_DirPort, Group_AuxPorts, "PWM2 spindle direction port", NULL, Format_Decimal, "-#0", "-1", max_dport, Setting_NonCoreFn, set_dir_port, get_dir_port, has_ports, { .reboot_required = On } },
{ Setting_SpindleInvertMask1, Group_Spindle, "Invert spindle 2 signals", NULL, Format_Bitfield, spindle_signals, NULL, NULL, Setting_IsExtendedFn, set_spindle_invert, get_int, NULL, { .reboot_required = On } },
{ Setting_Spindle_PWMPort, Group_AuxPorts, "PWM2 spindle PWM port", NULL, Format_Int8, "#0", "0", max_aport, Setting_NonCoreFn, set_pwm_port, get_pwm_port, NULL, { .reboot_required = On } },
{ Setting_RpmMax1, Group_Spindle, "Maximum spindle 2 speed", "RPM", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &sp1_settings.cfg.rpm_max, NULL, has_pwm },
{ Setting_RpmMin1, Group_Spindle, "Minimum spindle 2 speed", "RPM", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &sp1_settings.cfg.rpm_min, NULL, has_pwm },
{ Setting_PWMFreq1, Group_Spindle, "Spindle 2 PWM frequency", "Hz", Format_Decimal, "#####0", NULL, NULL, Setting_IsExtended, &sp1_settings.cfg.pwm_freq, NULL, has_freq },
{ Setting_PWMOffValue1, Group_Spindle, "Spindle 2 PWM off value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &sp1_settings.cfg.pwm_off_value, NULL, has_pwm },
{ Setting_PWMMinValue1, Group_Spindle, "Spindle 2 PWM min value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &sp1_settings.cfg.pwm_min_value, NULL, has_pwm },
{ Setting_PWMMaxValue1, Group_Spindle, "Spindle 2 PWM max value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &sp1_settings.cfg.pwm_max_value, NULL, has_pwm }
#if xENABLE_SPINDLE_LINEARIZATION
{ Setting_LinearSpindle1Piece1, Group_Spindle, "Spindle 2 linearisation, 1st point", NULL, Format_String, "x(39)", NULL, "39", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
#if SPINDLE_NPWM_PIECES > 1
{ Setting_LinearSpindle1Piece2, Group_Spindle, "Spindle 2 linearisation, 2nd point", NULL, Format_String, "x(39)", NULL, "39", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
#endif
#if SPINDLE_NPWM_PIECES > 2
{ Setting_LinearSpindle1Piece3, Group_Spindle, "Spindle 2 linearisation, 3rd point", NULL, Format_String, "x(39)", NULL, "39", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
#endif
#if SPINDLE_NPWM_PIECES > 3
{ Setting_LinearSpindle1Piece4, Group_Spindle, "Spindle 2 linearisation, 4th point", NULL, Format_String, "x(39)", NULL, "39", Setting_IsExtendedFn, set_linear_piece, get_linear_piece, NULL },
#endif
#endif
};
#ifndef NO_SETTINGS_DESCRIPTIONS
static const setting_descr_t spindle1_settings_descr[] = {
{ Setting_Spindle_OnPort, "On/off aux port." },
{ Setting_Spindle_DirPort, "Direction aux port, set to -1 if not required." },
{ Setting_SpindleInvertMask1, "Inverts the spindle on, counterclockwise and PWM signals (active low)." },
{ Setting_Spindle_PWMPort, "Spindle analog aux port. Must be PWM capable!" },
{ Setting_RpmMax1, "Maximum spindle speed." },
{ Setting_RpmMin1, "Minimum spindle speed." },
{ Setting_PWMFreq1, "PWM frequency." },
{ Setting_PWMOffValue1, "PWM off value in percent (duty cycle)." },
{ Setting_PWMMinValue1, "PWM min value in percent (duty cycle)." },
{ Setting_PWMMaxValue1, "PWM max value in percent (duty cycle)." }
#if xENABLE_SPINDLE_LINEARIZATION
{ Setting_LinearSpindle1Piece1, "Comma separated list of values: RPM_MIN, RPM_LINE_A1, RPM_LINE_B1, set to blank to disable." },
#if SPINDLE_NPWM_PIECES > 1
{ Setting_LinearSpindle1Piece2, "Comma separated list of values: RPM_POINT12, RPM_LINE_A2, RPM_LINE_B2, set to blank to disable." },
#endif
#if SPINDLE_NPWM_PIECES > 2
{ Setting_LinearSpindle1Piece3, "Comma separated list of values: RPM_POINT23, RPM_LINE_A3, RPM_LINE_B3, set to blank to disable." },
#endif
#if SPINDLE_NPWM_PIECES > 3
{ Setting_LinearSpindle1Piece4, "Comma separated list of values: RPM_POINT34, RPM_LINE_A4, RPM_LINE_B4, set to blank to disable." },
#endif
#endif
};
#endif
static void spindle1_settings_changed (settings_t *settings, settings_changed_flags_t changed)
{
UNUSED(changed);
if(on_settings_changed) {
changed.spindle = On;
on_settings_changed(&sp1_settings);
}
}
static void spindle1_settings_save (void)
{
hal.nvs.memcpy_to_nvs(nvs_address, (uint8_t *)&sp1_settings, sizeof(spindle1_settings_t), true);
}
static void spindle1_settings_restore (void)
{
static const spindle_settings_t defaults = {
.rpm_max = DEFAULT_SPINDLE_RPM_MAX,
.rpm_min = DEFAULT_SPINDLE_RPM_MIN,
.flags.pwm_disable = false,
.flags.enable_rpm_controlled = DEFAULT_SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED,
.invert.on = DEFAULT_INVERT_SPINDLE_ENABLE_PIN,
.invert.ccw = DEFAULT_INVERT_SPINDLE_CCW_PIN,
.invert.pwm = DEFAULT_INVERT_SPINDLE_PWM_PIN,
.pwm_freq = DEFAULT_SPINDLE_PWM_FREQ,
.pwm_off_value = DEFAULT_SPINDLE_PWM_OFF_VALUE,
.pwm_min_value = DEFAULT_SPINDLE_PWM_MIN_VALUE,
.pwm_max_value = DEFAULT_SPINDLE_PWM_MAX_VALUE,
.at_speed_tolerance = DEFAULT_SPINDLE_AT_SPEED_TOLERANCE,
.ppr = DEFAULT_SPINDLE_PPR,
.pid.p_gain = DEFAULT_SPINDLE_P_GAIN,
.pid.i_gain = DEFAULT_SPINDLE_I_GAIN,
.pid.d_gain = DEFAULT_SPINDLE_D_GAIN,
.pid.i_max_error = DEFAULT_SPINDLE_I_MAX,
#if ENABLE_SPINDLE_LINEARIZATION
#if SPINDLE_NPWM_PIECES > 0
.pwm_piece[0] = { .rpm = DEFAULT_RPM_POINT01, .start = DEFAULT_RPM_LINE_A1, .end = DEFAULT_RPM_LINE_B1 },
#endif
#if SPINDLE_NPWM_PIECES > 1
.pwm_piece[1] = { .rpm = DEFAULT_RPM_POINT12, .start = DEFAULT_RPM_LINE_A2, .end = DEFAULT_RPM_LINE_B2 },
#endif
#if SPINDLE_NPWM_PIECES > 2
.pwm_piece[2] = { .rpm = DEFAULT_RPM_POINT23, .start = DEFAULT_RPM_LINE_A3, .end = DEFAULT_RPM_LINE_B3 },
#endif
#if SPINDLE_NPWM_PIECES > 3
.pwm_piece[3] = { .rpm = DEFAULT_RPM_POINT34, .start = DEFAULT_RPM_LINE_A4, .end = DEFAULT_RPM_LINE_B4 },
#endif
#else
#if SPINDLE_NPWM_PIECES > 0
.pwm_piece[0] = { .rpm = NAN, .start = 0.0f, .end = 0.0f },
#endif
#if SPINDLE_NPWM_PIECES > 1
.pwm_piece[1] = { .rpm = NAN, .start = 0.0f, .end = 0.0f },
#endif
#if SPINDLE_NPWM_PIECES > 2
.pwm_piece[2] = { .rpm = NAN, .start = 0.0f, .end = 0.0f },
#endif
#if SPINDLE_NPWM_PIECES > 3
.pwm_piece[3] = { .rpm = NAN, .start = 0.0f, .end = 0.0f },
#endif
#endif
};
memcpy(&sp1_settings.cfg, &defaults, sizeof(spindle_settings_t));
hal.nvs.memcpy_to_nvs(nvs_address, (uint8_t *)&sp1_settings, sizeof(spindle1_settings_t), true);
}
static void spindle1_settings_load (void)
{
if((hal.nvs.memcpy_from_nvs((uint8_t *)&sp1_settings, nvs_address, sizeof(spindle1_settings_t), true) != NVS_TransferResult_OK))
spindle1_settings_restore();
}
static setting_details_t spindle1_setting_details = {
.settings = spindle1_settings,
.n_settings = sizeof(spindle1_settings) / sizeof(setting_detail_t),
#ifndef NO_SETTINGS_DESCRIPTIONS
.descriptions = spindle1_settings_descr,
.n_descriptions = sizeof(spindle1_settings_descr) / sizeof(setting_descr_t),
#endif
.load = spindle1_settings_load,
.restore = spindle1_settings_restore,
.save = spindle1_settings_save,
.on_changed = spindle1_settings_changed
};
static bool pwm_count (xbar_t *properties, uint8_t port, void *data)
{
*((uint32_t *)data) += 1;
sp1_settings.port_pwm = max(sp1_settings.port_pwm, port);
return false;
}
static bool check_pwm_ports (void)
{
uint32_t n_pwm_out = 0;
ioports_enumerate(Port_Analog, Port_Output, (pin_cap_t){ .pwm = On, .claimable = On }, pwm_count, &n_pwm_out);
return n_pwm_out != 0;
}
spindle1_settings_t *spindle1_settings_add (bool claim_ports)
{
if((ports_ok = claim_ports && hal.port.num_digital_out > 0 && check_pwm_ports())) {
sp1_settings.port_on = hal.port.num_digital_out - 1;
sp1_settings.port_dir = hal.port.num_digital_out > 1 ? hal.port.num_digital_out - 2 : 255;
strcpy(max_aport, uitoa(sp1_settings.port_pwm));
strcpy(max_dport, uitoa(hal.port.num_digital_out - 1));
}
return nvs_address == 0 && (!claim_ports || ports_ok) && (nvs_address = nvs_alloc(sizeof(spindle1_settings_t))) ? &sp1_settings : NULL;
}
void spindle1_settings_register (spindle_cap_t cap, spindle1_settings_changed_ptr on_changed)
{
on_settings_changed = on_changed;
settings_register(&spindle1_setting_details);
spindle_cap = cap;
spindle_state_t spindle_state = { .on = On };
spindle_state.ccw = cap.direction;
spindle_state.pwm = cap.pwm_invert;
setting_remove_elements(Setting_SpindleInvertMask1, spindle_state.mask);
}
#endif
+42 -12
View File
@@ -7,18 +7,18 @@
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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SPINDLE_CONTROL_H_
@@ -83,7 +83,8 @@ typedef union {
rpm_range_locked :1, //!< Spindle RPM range (min, max) not inherited from settings.
gpio_controlled :1, //!< On/off and direction is controlled by GPIO.
cmd_controlled :1, //!< Command controlled, e.g. over ModBus.
unassigned :6;
cloned :1, //!< Spindle is cloned.
unassigned :5;
};
} spindle_cap_t;
@@ -101,9 +102,10 @@ typedef struct {
} spindle_data_t;
typedef enum {
SpindleData_Counters, //!< 0
SpindleData_RPM, //!< 1
SpindleData_AngularPosition //!< 2
SpindleData_Counters, //!< 0
SpindleData_RPM, //!< 1
SpindleData_AngularPosition, //!< 2
SpindleData_AtSpeed //!< 3
} spindle_data_request_t;
typedef enum {
@@ -196,7 +198,7 @@ typedef union {
uint8_t mask;
struct {
uint8_t enable_rpm_controlled :1, // PWM spindle only
unused :1,
laser_mode_disable :1, // PWM spindle only
type :5,
pwm_disable :1; // PWM spindle only
};
@@ -218,6 +220,24 @@ typedef struct {
spindle_settings_flags_t flags;
} spindle_settings_t;
typedef struct {
uint8_t port_on;
uint8_t port_dir;
uint8_t port_pwm;
spindle_settings_t cfg;
} spindle1_settings_t;
typedef union {
uint8_t value;
struct {
uint8_t invert_pwm :1, //!< NOTE: set (by driver) when inversion is done in code
always_on :1,
cloned :1,
laser_mode_disable :1,
unused :4;
};
} spindle_pwm_flags_t;
//!* \brief Precalculated values that may be set/used by HAL driver to speed up RPM to PWM conversions if variable spindle is supported. */
typedef struct spindle_pwm {
uint32_t f_clock;
@@ -228,9 +248,10 @@ typedef struct spindle_pwm {
uint_fast16_t max_value;
float rpm_min; //!< Minimum spindle RPM.
float pwm_gradient;
bool invert_pwm; //!< NOTE: set (by driver) when inversion is done in code
bool always_on;
bool cloned;
bool invert_pwm; //!< deprecated, use bit in flags instead
bool always_on; //!< deprecated, use bit in flags instead
bool cloned; //!< deprecated, use bit in flags instead
spindle_pwm_flags_t flags;
int_fast16_t offset;
uint_fast16_t n_pieces;
pwm_piece_t piece[SPINDLE_NPWM_PIECES];
@@ -362,4 +383,13 @@ bool spindle_is_on (void);
spindle_ptrs_t *spindle_get (spindle_num_t spindle_num);
#if N_SPINDLE > 1
typedef void (*spindle1_settings_changed_ptr)(spindle1_settings_t *settings);
spindle1_settings_t *spindle1_settings_add (bool claim_ports);
void spindle1_settings_register (spindle_cap_t cap, spindle1_settings_changed_ptr on_changed);
#endif
#endif // _SPINDLE_CONTROL_H_
+35 -12
View File
@@ -6,18 +6,18 @@
Copyright (c) 2017-2024 Terje Io
Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea mResearch 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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
@@ -347,7 +347,7 @@ static status_code_t toggle_optional_stop (sys_state_t state, char *args)
static status_code_t check_mode (sys_state_t state, char *args)
{
if (state == STATE_CHECK_MODE) {
// Perform reset when toggling off. Check g-code mode should only work if Grbl
// Perform reset when toggling off. Check g-code mode should only work if grblHAL
// is idle and ready, regardless of alarm locks. This is mainly to keep things
// simple and consistent.
mc_reset();
@@ -901,12 +901,12 @@ PROGMEM static const sys_command_t sys_commands[] = {
{ "N0", set_startup_line0, {}, { .str = "N0=<gcode> - set startup line 0" } },
{ "N1", set_startup_line1, {}, { .str = "N1=<gcode> - set startup line 1" } },
{ "EA", enumerate_alarms, { .noargs = On, .allow_blocking = On }, { .str = "enumerate alarms" } },
{ "EAG", enumerate_alarms_grblformatted, { .noargs = On, .allow_blocking = On }, { .str = "enumerate alarms, Grbl formatted" } },
{ "EAG", enumerate_alarms_grblformatted, { .noargs = On, .allow_blocking = On }, { .str = "enumerate alarms, grblHAL formatted" } },
{ "EE", enumerate_errors, { .noargs = On, .allow_blocking = On }, { .str = "enumerate status codes" } },
{ "EEG", enumerate_errors_grblformatted, { .noargs = On, .allow_blocking = On }, { .str = "enumerate status codes, Grbl formatted" } },
{ "EEG", enumerate_errors_grblformatted, { .noargs = On, .allow_blocking = On }, { .str = "enumerate status codes, grblHAL formatted" } },
{ "EG", enumerate_groups, { .noargs = On, .allow_blocking = On }, { .str = "enumerate setting groups" } },
{ "ES", enumerate_settings, { .noargs = On, .allow_blocking = On }, { .str = "enumerate settings" } },
{ "ESG", enumerate_settings_grblformatted, { .noargs = On, .allow_blocking = On }, { .str = "enumerate settings, Grbl formatted" } },
{ "ESG", enumerate_settings_grblformatted, { .noargs = On, .allow_blocking = On }, { .str = "enumerate settings, grblHAL formatted" } },
{ "ESH", enumerate_settings_halformatted, { .noargs = On, .allow_blocking = On }, { .str = "enumerate settings, grblHAL formatted" } },
{ "E*", enumerate_all, { .noargs = On, .allow_blocking = On }, { .str = "enumerate alarms, status codes and settings" } },
{ "PINS", enumerate_pins, { .noargs = On, .allow_blocking = On, .help_fn = On }, { .fn = help_pins } },
@@ -986,9 +986,9 @@ void system_command_help (void)
/*! \brief Directs and executes one line of input from protocol_process.
While mostly incoming streaming g-code blocks, this also executes Grbl internal commands, such as
While mostly incoming streaming g-code blocks, this also executes grblHAL internal commands, such as
settings, initiating the homing cycle, and toggling switch states. This differs from
the realtime command module by being susceptible to when Grbl is ready to execute the
the realtime command module by being susceptible to when grblHAL is ready to execute the
next line during a cycle, so for switches like block delete, the switch only effects
the lines that are processed afterward, not necessarily real-time during a cycle,
since there are motions already stored in the buffer. However, this 'lag' should not
@@ -1104,14 +1104,37 @@ status_code_t system_execute_line (char *line)
return retval;
}
// End system commands
// End system $-commands
/*! \brief Called on homing state changes.
Clears the tool length offset (TLO) when linear axis or X- or Z-axis is homed in lathe mode.
Typically called on the grbl.on_homing complete event.
\param id a \a axes_signals_t holding the axis flags that homed status was changed for.
*/
void system_clear_tlo_reference (axes_signals_t homing_cycle)
{
plane_t plane;
#if TOOL_LENGTH_OFFSET_AXIS >= 0
plane.axis_linear = TOOL_LENGTH_OFFSET_AXIS;
#else
gc_get_plane_data(&plane, gc_state.modal.plane_select);
#endif
if(homing_cycle.mask & (settings.mode == Mode_Lathe ? (X_AXIS_BIT|Z_AXIS_BIT) : bit(plane.axis_linear))) {
if(sys.tlo_reference_set.mask != 0) {
sys.tlo_reference_set.mask = 0; // Invalidate tool length offset reference
system_add_rt_report(Report_TLOReference);
}
}
}
/*! \brief Called on a work coordinate (WCO) changes.
If configured waits for the planner buffer to empty then fires the
grbl.on_wco_changed event and sets the #Report_WCO flag to add
the WCO report element to the next status report.
*/
*/
void system_flag_wco_change (void)
{
if(!settings.status_report.sync_on_wco_change)
+9 -6
View File
@@ -6,18 +6,18 @@
Copyright (c) 2017-2024 Terje Io
Copyright (c) 2014-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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SYSTEM_H_
@@ -186,8 +186,9 @@ typedef enum {
Report_Encoder = (1 << 14),
Report_TLOReference = (1 << 15),
Report_Fan = (1 << 16),
Report_SpindleId = (1 << 17),
Report_CycleStart = (1 << 30),
Report_All = 0x8001FFFF
Report_All = 0x8003FFFF
} report_tracking_t;
typedef union {
@@ -210,7 +211,8 @@ typedef union {
encoder :1, //!< Add encoder information (optional: to be added by driver).
tlo_reference :1, //!< Tool length offset reference changed.
fan :1, //!< Fan on/off changed.
unassigned :13, //
spindle_id :1, //!< Spindle changed
unassigned :12, //
cycle_start :1, //!< Cycle start signal triggered. __NOTE:__ do __NOT__ add to Report_All enum above!
all :1; //!< Set when CMD_STATUS_REPORT_ALL is requested, may be used by user code.
};
@@ -355,6 +357,7 @@ void system_command_help (void);
void system_output_help (const sys_command_t *commands, uint32_t num_commands);
void system_register_commands (sys_commands_t *commands);
void system_clear_tlo_reference (axes_signals_t homing_cycle);
void system_add_rt_report (report_tracking_t report);
report_tracking_flags_t system_get_rt_report_flags (void);
+22 -24
View File
@@ -7,18 +7,18 @@
Copyright (c) 2020-2024 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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
@@ -47,6 +47,17 @@ static coord_data_t target = {0}, previous;
static driver_reset_ptr driver_reset = NULL;
static enqueue_realtime_command_ptr enqueue_realtime_command = NULL;
static control_signals_callback_ptr control_interrupt_callback = NULL;
static on_homing_completed_ptr on_homing_completed = NULL;
// Clear tool length offset on homing
static void tc_on_homing_complete (axes_signals_t homing_cycle, bool success)
{
if(on_homing_completed)
on_homing_completed(homing_cycle, success);
if(settings.tool_change.mode != ToolChange_Disabled)
system_clear_tlo_reference(homing_cycle);
}
// Set tool offset on successful $TPW probe, prompt for retry on failure.
// Called via probe completed event.
@@ -402,6 +413,8 @@ static status_code_t tool_change (parser_state_t *parser_state)
// TODO: change to survive a warm reset?
void tc_init (void)
{
static bool on_homing_subscribed = false;
if(hal.driver_cap.atc) // Do not override driver tool change implementation!
return;
@@ -423,6 +436,11 @@ void tc_init (void)
hal.tool.select = tool_select;
hal.tool.change = tool_change;
grbl.on_toolchange_ack = on_toolchange_ack;
if(!on_homing_subscribed) {
on_homing_subscribed = true;
on_homing_completed = grbl.on_homing_completed;
grbl.on_homing_completed = tc_on_homing_complete;
}
if(driver_reset == NULL) {
driver_reset = hal.driver_reset;
hal.driver_reset = reset;
@@ -430,26 +448,6 @@ void tc_init (void)
}
}
void tc_clear_tlo_reference (axes_signals_t homing_cycle)
{
if(settings.tool_change.mode != ToolChange_Disabled) {
plane_t plane;
#if TOOL_LENGTH_OFFSET_AXIS >= 0
plane.axis_linear = TOOL_LENGTH_OFFSET_AXIS;
#else
gc_get_plane_data(&plane, gc_state.modal.plane_select);
#endif
if(homing_cycle.mask & (settings.mode == Mode_Lathe ? (X_AXIS_BIT|Z_AXIS_BIT) : bit(plane.axis_linear))) {
if(sys.tlo_reference_set.mask != 0) {
sys.tlo_reference_set.mask = 0; // Invalidate tool length offset reference
system_add_rt_report(Report_TLOReference);
}
}
}
}
// Perform a probe cycle: set tool length offset and restart job if successful.
// Note: tool length offset is set by the on_probe_completed event handler.
// Called by the $TPW system command.
+5 -6
View File
@@ -5,20 +5,20 @@
Part of grblHAL
Copyright (c) 2020 Terje Io
Copyright (c) 2020-2024 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 <http://www.gnu.org/licenses/>.
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TOOL_CHANGE_H_
@@ -26,6 +26,5 @@
void tc_init (void);
status_code_t tc_probe_workpiece (void);
void tc_clear_tlo_reference (axes_signals_t homing_cycle);
#endif