update code base to Marlin 2.0.9.2

This commit is contained in:
Stefan Kalscheuer
2021-10-03 18:57:12 +02:00
parent b9d7ba838e
commit 7077da3591
2617 changed files with 332093 additions and 103438 deletions

23
Marlin/src/module/stepper/L64xx.cpp Executable file → Normal file
View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@@ -55,6 +55,15 @@
#if AXIS_IS_L64XX(Z4)
L64XX_CLASS(Z4) stepperZ4(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(I)
L64XX_CLASS(I) stepperI(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(J)
L64XX_CLASS(J) stepperJ(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(K)
L64XX_CLASS(K) stepperK(L6470_CHAIN_SS_PIN);
#endif
#if AXIS_IS_L64XX(E0)
L64XX_CLASS(E0) stepperE0(L6470_CHAIN_SS_PIN);
#endif
@@ -196,6 +205,18 @@ void L64XX_Marlin::init_to_defaults() {
#if AXIS_IS_L64XX(Z3)
L6470_INIT_CHIP(Z3);
#endif
#if AXIS_IS_L64XX(Z4)
L6470_INIT_CHIP(Z4);
#endif
#if AXIS_IS_L64XX(I)
L6470_INIT_CHIP(I);
#endif
#if AXIS_IS_L64XX(J)
L6470_INIT_CHIP(J);
#endif
#if AXIS_IS_L64XX(K)
L6470_INIT_CHIP(K);
#endif
#if AXIS_IS_L64XX(E0)
L6470_INIT_CHIP(E0);
#endif

108
Marlin/src/module/stepper/L64xx.h Executable file → Normal file
View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
@@ -45,7 +45,7 @@
#if AXIS_IS_L64XX(X)
extern L64XX_CLASS(X) stepperX;
#define X_ENABLE_INIT() NOOP
#define X_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperX.free())
#define X_ENABLE_WRITE(STATE) (STATE ? stepperX.hardStop() : stepperX.free())
#define X_ENABLE_READ() (stepperX.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_X(L6474)
#define X_DIR_INIT() SET_OUTPUT(X_DIR_PIN)
@@ -65,7 +65,7 @@
#if AXIS_IS_L64XX(Y)
extern L64XX_CLASS(Y) stepperY;
#define Y_ENABLE_INIT() NOOP
#define Y_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperY.free())
#define Y_ENABLE_WRITE(STATE) (STATE ? stepperY.hardStop() : stepperY.free())
#define Y_ENABLE_READ() (stepperY.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_Y(L6474)
#define Y_DIR_INIT() SET_OUTPUT(Y_DIR_PIN)
@@ -85,7 +85,7 @@
#if AXIS_IS_L64XX(Z)
extern L64XX_CLASS(Z) stepperZ;
#define Z_ENABLE_INIT() NOOP
#define Z_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperZ.free())
#define Z_ENABLE_WRITE(STATE) (STATE ? stepperZ.hardStop() : stepperZ.free())
#define Z_ENABLE_READ() (stepperZ.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_Z(L6474)
#define Z_DIR_INIT() SET_OUTPUT(Z_DIR_PIN)
@@ -105,7 +105,7 @@
#if HAS_X2_ENABLE && AXIS_IS_L64XX(X2)
extern L64XX_CLASS(X2) stepperX2;
#define X2_ENABLE_INIT() NOOP
#define X2_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperX2.free())
#define X2_ENABLE_WRITE(STATE) (STATE ? stepperX2.hardStop() : stepperX2.free())
#define X2_ENABLE_READ() (stepperX2.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_X2(L6474)
#define X2_DIR_INIT() SET_OUTPUT(X2_DIR_PIN)
@@ -126,7 +126,7 @@
#if HAS_Y2_ENABLE && AXIS_IS_L64XX(Y2)
extern L64XX_CLASS(Y2) stepperY2;
#define Y2_ENABLE_INIT() NOOP
#define Y2_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperY2.free())
#define Y2_ENABLE_WRITE(STATE) (STATE ? stepperY2.hardStop() : stepperY2.free())
#define Y2_ENABLE_READ() (stepperY2.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_Y2(L6474)
#define Y2_DIR_INIT() SET_OUTPUT(Y2_DIR_PIN)
@@ -147,7 +147,7 @@
#if HAS_Z2_ENABLE && AXIS_IS_L64XX(Z2)
extern L64XX_CLASS(Z2) stepperZ2;
#define Z2_ENABLE_INIT() NOOP
#define Z2_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperZ2.free())
#define Z2_ENABLE_WRITE(STATE) (STATE ? stepperZ2.hardStop() : stepperZ2.free())
#define Z2_ENABLE_READ() (stepperZ2.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_Z2(L6474)
#define Z2_DIR_INIT() SET_OUTPUT(Z2_DIR_PIN)
@@ -168,7 +168,7 @@
#if HAS_Z3_ENABLE && AXIS_IS_L64XX(Z3)
extern L64XX_CLASS(Z3) stepperZ3;
#define Z3_ENABLE_INIT() NOOP
#define Z3_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperZ3.free())
#define Z3_ENABLE_WRITE(STATE) (STATE ? stepperZ3.hardStop() : stepperZ3.free())
#define Z3_ENABLE_READ() (stepperZ3.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_Z3(L6474)
#define Z3_DIR_INIT() SET_OUTPUT(Z3_DIR_PIN)
@@ -189,7 +189,7 @@
#if HAS_Z4_ENABLE && AXIS_IS_L64XX(Z4)
extern L64XX_CLASS(Z4) stepperZ4;
#define Z4_ENABLE_INIT() NOOP
#define Z4_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperZ4.free())
#define Z4_ENABLE_WRITE(STATE) (STATE ? stepperZ4.hardStop() : stepperZ4.free())
#define Z4_ENABLE_READ() (stepperZ4.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_Z4(L6474)
#define Z4_DIR_INIT() SET_OUTPUT(Z4_DIR_PIN)
@@ -206,11 +206,71 @@
#define DISABLE_STEPPER_Z4() stepperZ4.free()
#endif
// I Stepper
#if AXIS_IS_L64XX(I)
extern L64XX_CLASS(I) stepperI;
#define I_ENABLE_INIT() NOOP
#define I_ENABLE_WRITE(STATE) (STATE ? stepperI.hardStop() : stepperI.free())
#define I_ENABLE_READ() (stepperI.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_I(L6474)
#define I_DIR_INIT() SET_OUTPUT(I_DIR_PIN)
#define I_DIR_WRITE(STATE) L6474_DIR_WRITE(I, STATE)
#define I_DIR_READ() READ(I_DIR_PIN)
#else
#define I_DIR_INIT() NOOP
#define I_DIR_WRITE(STATE) L64XX_DIR_WRITE(I, STATE)
#define I_DIR_READ() (stepper##I.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_I(L6470)
#define DISABLE_STEPPER_I() stepperI.free()
#endif
#endif
#endif
// J Stepper
#if AXIS_IS_L64XX(J)
extern L64XX_CLASS(J) stepperJ;
#define J_ENABLE_INIT() NOOP
#define J_ENABLE_WRITE(STATE) (STATE ? stepperJ.hardStop() : stepperJ.free())
#define J_ENABLE_READ() (stepperJ.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_J(L6474)
#define J_DIR_INIT() SET_OUTPUT(J_DIR_PIN)
#define J_DIR_WRITE(STATE) L6474_DIR_WRITE(J, STATE)
#define J_DIR_READ() READ(J_DIR_PIN)
#else
#define J_DIR_INIT() NOOP
#define J_DIR_WRITE(STATE) L64XX_DIR_WRITE(J, STATE)
#define J_DIR_READ() (stepper##J.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_J(L6470)
#define DISABLE_STEPPER_J() stepperJ.free()
#endif
#endif
#endif
// K Stepper
#if AXIS_IS_L64XX(K)
extern L64XX_CLASS(K) stepperK;
#define K_ENABLE_INIT() NOOP
#define K_ENABLE_WRITE(STATE) (STATE ? stepperK.hardStop() : stepperK.free())
#define K_ENABLE_READ() (stepperK.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_K(L6474)
#define K_DIR_INIT() SET_OUTPUT(K_DIR_PIN)
#define K_DIR_WRITE(STATE) L6474_DIR_WRITE(K, STATE)
#define K_DIR_READ() READ(K_DIR_PIN)
#else
#define K_DIR_INIT() NOOP
#define K_DIR_WRITE(STATE) L64XX_DIR_WRITE(K, STATE)
#define K_DIR_READ() (stepper##K.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_K(L6470)
#define DISABLE_STEPPER_K() stepperK.free()
#endif
#endif
#endif
// E0 Stepper
#if AXIS_IS_L64XX(E0)
extern L64XX_CLASS(E0) stepperE0;
#define E0_ENABLE_INIT() NOOP
#define E0_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE0.free())
#define E0_ENABLE_WRITE(STATE) (STATE ? stepperE0.hardStop() : stepperE0.free())
#define E0_ENABLE_READ() (stepperE0.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_E0(L6474)
#define E0_DIR_INIT() SET_OUTPUT(E0_DIR_PIN)
@@ -221,7 +281,7 @@
#define E0_DIR_WRITE(STATE) L64XX_DIR_WRITE(E0, STATE)
#define E0_DIR_READ() (stepper##E0.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_E0(L6470)
#define DISABLE_STEPPER_E0() do{ stepperE0.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define DISABLE_STEPPER_E0() do{ stepperE0.free(); }while(0)
#endif
#endif
#endif
@@ -230,7 +290,7 @@
#if AXIS_IS_L64XX(E1)
extern L64XX_CLASS(E1) stepperE1;
#define E1_ENABLE_INIT() NOOP
#define E1_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE1.free())
#define E1_ENABLE_WRITE(STATE) (STATE ? stepperE1.hardStop() : stepperE1.free())
#define E1_ENABLE_READ() (stepperE1.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_E1(L6474)
#define E1_DIR_INIT() SET_OUTPUT(E1_DIR_PIN)
@@ -241,7 +301,7 @@
#define E1_DIR_WRITE(STATE) L64XX_DIR_WRITE(E1, STATE)
#define E1_DIR_READ() (stepper##E1.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_E1(L6470)
#define DISABLE_STEPPER_E1() do{ stepperE1.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define DISABLE_STEPPER_E1() do{ stepperE1.free(); }while(0)
#endif
#endif
#endif
@@ -250,7 +310,7 @@
#if AXIS_IS_L64XX(E2)
extern L64XX_CLASS(E2) stepperE2;
#define E2_ENABLE_INIT() NOOP
#define E2_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE2.free())
#define E2_ENABLE_WRITE(STATE) (STATE ? stepperE2.hardStop() : stepperE2.free())
#define E2_ENABLE_READ() (stepperE2.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_E2(L6474)
#define E2_DIR_INIT() SET_OUTPUT(E2_DIR_PIN)
@@ -261,7 +321,7 @@
#define E2_DIR_WRITE(STATE) L64XX_DIR_WRITE(E2, STATE)
#define E2_DIR_READ() (stepper##E2.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_E2(L6470)
#define DISABLE_STEPPER_E2() do{ stepperE2.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define DISABLE_STEPPER_E2() do{ stepperE2.free(); }while(0)
#endif
#endif
#endif
@@ -270,7 +330,7 @@
#if AXIS_IS_L64XX(E3)
extern L64XX_CLASS(E3) stepperE3;
#define E3_ENABLE_INIT() NOOP
#define E3_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE3.free())
#define E3_ENABLE_WRITE(STATE) (STATE ? stepperE3.hardStop() : stepperE3.free())
#define E3_ENABLE_READ() (stepperE3.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_E3(L6474)
#define E3_DIR_INIT() SET_OUTPUT(E3_DIR_PIN)
@@ -287,7 +347,7 @@
#if AXIS_IS_L64XX(E4)
extern L64XX_CLASS(E4) stepperE4;
#define E4_ENABLE_INIT() NOOP
#define E4_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE4.free())
#define E4_ENABLE_WRITE(STATE) (STATE ? stepperE4.hardStop() : stepperE4.free())
#define E4_ENABLE_READ() (stepperE4.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_E4(L6474)
#define E4_DIR_INIT() SET_OUTPUT(E4_DIR_PIN)
@@ -298,7 +358,7 @@
#define E4_DIR_WRITE(STATE) L64XX_DIR_WRITE(E4, STATE)
#define E4_DIR_READ() (stepper##E4.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_E4(L6470)
#define DISABLE_STEPPER_E4() do{ stepperE4.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define DISABLE_STEPPER_E4() do{ stepperE4.free(); }while(0)
#endif
#endif
#endif
@@ -307,7 +367,7 @@
#if AXIS_IS_L64XX(E5)
extern L64XX_CLASS(E5) stepperE5;
#define E5_ENABLE_INIT() NOOP
#define E5_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE5.free())
#define E5_ENABLE_WRITE(STATE) (STATE ? stepperE5.hardStop() : stepperE5.free())
#define E5_ENABLE_READ() (stepperE5.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_E5(L6474)
#define E5_DIR_INIT() SET_OUTPUT(E5_DIR_PIN)
@@ -318,7 +378,7 @@
#define E5_DIR_WRITE(STATE) L64XX_DIR_WRITE(E5, STATE)
#define E5_DIR_READ() (stepper##E5.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_E5(L6470)
#define DISABLE_STEPPER_E5() do{ stepperE5.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define DISABLE_STEPPER_E5() do{ stepperE5.free(); }while(0)
#endif
#endif
#endif
@@ -327,7 +387,7 @@
#if AXIS_IS_L64XX(E6)
extern L64XX_CLASS(E6) stepperE6;
#define E6_ENABLE_INIT() NOOP
#define E6_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE6.free())
#define E6_ENABLE_WRITE(STATE) (STATE ? stepperE6.hardStop() : stepperE6.free())
#define E6_ENABLE_READ() (stepperE6.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_E6(L6474)
#define E6_DIR_INIT() SET_OUTPUT(E6_DIR_PIN)
@@ -338,7 +398,7 @@
#define E6_DIR_WRITE(STATE) L64XX_DIR_WRITE(E6, STATE)
#define E6_DIR_READ() (stepper##E6.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_E6(L6470)
#define DISABLE_STEPPER_E6() do{ stepperE6.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define DISABLE_STEPPER_E6() do{ stepperE6.free(); }while(0)
#endif
#endif
#endif
@@ -347,7 +407,7 @@
#if AXIS_IS_L64XX(E7)
extern L64XX_CLASS(E7) stepperE7;
#define E7_ENABLE_INIT() NOOP
#define E7_ENABLE_WRITE(STATE) (STATE ? NOOP : stepperE7.free())
#define E7_ENABLE_WRITE(STATE) (STATE ? stepperE7.hardStop() : stepperE7.free())
#define E7_ENABLE_READ() (stepperE7.getStatus() & STATUS_HIZ)
#if AXIS_DRIVER_TYPE_E7(L6474)
#define E7_DIR_INIT() SET_OUTPUT(E7_DIR_PIN)
@@ -358,7 +418,7 @@
#define E7_DIR_WRITE(STATE) L64XX_DIR_WRITE(E7, STATE)
#define E7_DIR_READ() (stepper##E7.getStatus() & STATUS_DIR);
#if AXIS_DRIVER_TYPE_E7(L6470)
#define DISABLE_STEPPER_E7() do{ stepperE7.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define DISABLE_STEPPER_E7() do{ stepperE7.free(); }while(0)
#endif
#endif
#endif

24
Marlin/src/module/stepper/TMC26X.cpp Executable file → Normal file
View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@@ -30,7 +30,7 @@
//
// TMC26X Driver objects and inits
//
#if HAS_DRIVER(TMC26X)
#if HAS_TMC26X
#include "TMC26X.h"
@@ -60,6 +60,15 @@
#if AXIS_DRIVER_TYPE_Z4(TMC26X)
_TMC26X_DEFINE(Z4);
#endif
#if AXIS_DRIVER_TYPE_I(TMC26X)
_TMC26X_DEFINE(I);
#endif
#if AXIS_DRIVER_TYPE_J(TMC26X)
_TMC26X_DEFINE(J);
#endif
#if AXIS_DRIVER_TYPE_K(TMC26X)
_TMC26X_DEFINE(K);
#endif
#if AXIS_DRIVER_TYPE_E0(TMC26X)
_TMC26X_DEFINE(E0);
#endif
@@ -115,6 +124,15 @@ void tmc26x_init_to_defaults() {
#if AXIS_DRIVER_TYPE_Z4(TMC26X)
_TMC26X_INIT(Z4);
#endif
#if AXIS_DRIVER_TYPE_I(TMC26X)
_TMC26X_INIT(I);
#endif
#if AXIS_DRIVER_TYPE_J(TMC26X)
_TMC26X_INIT(J);
#endif
#if AXIS_DRIVER_TYPE_K(TMC26X)
_TMC26X_INIT(K);
#endif
#if AXIS_DRIVER_TYPE_E0(TMC26X)
_TMC26X_INIT(E0);
#endif
@@ -141,4 +159,4 @@ void tmc26x_init_to_defaults() {
#endif
}
#endif // TMC26X
#endif // HAS_TMC26X

32
Marlin/src/module/stepper/TMC26X.h Executable file → Normal file
View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
@@ -31,11 +31,7 @@
// TMC26X drivers have STEP/DIR on normal pins, but ENABLE via SPI
#include <SPI.h>
#if defined(STM32GENERIC) && defined(STM32F7)
#include "../../HAL/STM32_F4_F7/STM32F7/TMC2660.h"
#else
#include <TMC26XStepper.h>
#endif
#include <TMC26XStepper.h>
void tmc26x_init_to_defaults();
@@ -103,6 +99,30 @@ void tmc26x_init_to_defaults();
#define Z4_ENABLE_READ() stepperZ4.isEnabled()
#endif
// I Stepper
#if HAS_I_ENABLE && AXIS_DRIVER_TYPE_I(TMC26X)
extern TMC26XStepper stepperI;
#define I_ENABLE_INIT() NOOP
#define I_ENABLE_WRITE(STATE) stepperI.setEnabled(STATE)
#define I_ENABLE_READ() stepperI.isEnabled()
#endif
// J Stepper
#if HAS_J_ENABLE && AXIS_DRIVER_TYPE_J(TMC26X)
extern TMC26XStepper stepperJ;
#define J_ENABLE_INIT() NOOP
#define J_ENABLE_WRITE(STATE) stepperJ.setEnabled(STATE)
#define J_ENABLE_READ() stepperJ.isEnabled()
#endif
// K Stepper
#if HAS_K_ENABLE && AXIS_DRIVER_TYPE_K(TMC26X)
extern TMC26XStepper stepperK;
#define K_ENABLE_INIT() NOOP
#define K_ENABLE_WRITE(STATE) stepperK.setEnabled(STATE)
#define K_ENABLE_READ() stepperK.isEnabled()
#endif
// E0 Stepper
#if AXIS_DRIVER_TYPE_E0(TMC26X)
extern TMC26XStepper stepperE0;

25
Marlin/src/module/stepper/indirection.cpp Executable file → Normal file
View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@@ -33,21 +33,16 @@
#include "indirection.h"
void restore_stepper_drivers() {
#if HAS_TRINAMIC_CONFIG
restore_trinamic_drivers();
#endif
TERN_(HAS_TRINAMIC_CONFIG, restore_trinamic_drivers());
}
void reset_stepper_drivers() {
#if HAS_DRIVER(TMC26X)
tmc26x_init_to_defaults();
#endif
#if HAS_L64XX
L64xxManager.init_to_defaults();
#endif
#if HAS_TRINAMIC_CONFIG
reset_trinamic_drivers();
#endif
TERN_(HAS_TMC26X, tmc26x_init_to_defaults());
TERN_(HAS_L64XX, L64xxManager.init_to_defaults());
TERN_(HAS_TRINAMIC_CONFIG, reset_trinamic_drivers());
}
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
// Flags to optimize XYZ Enabled state
xyz_bool_t axis_sw_enabled; // = { false, false, false }
#endif

336
Marlin/src/module/stepper/indirection.h Executable file → Normal file
View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
@@ -36,7 +36,7 @@
#include "L64xx.h"
#endif
#if HAS_DRIVER(TMC26X)
#if HAS_TMC26X
#include "TMC26X.h"
#endif
@@ -44,7 +44,7 @@
#include "trinamic.h"
#endif
void restore_stepper_drivers(); // Called by PSU_ON
void restore_stepper_drivers(); // Called by powerManager.power_on()
void reset_stepper_drivers(); // Called by settings.load / settings.reset
// X Stepper
@@ -65,38 +65,42 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#define X_STEP_READ() bool(READ(X_STEP_PIN))
// Y Stepper
#ifndef Y_ENABLE_INIT
#define Y_ENABLE_INIT() SET_OUTPUT(Y_ENABLE_PIN)
#define Y_ENABLE_WRITE(STATE) WRITE(Y_ENABLE_PIN,STATE)
#define Y_ENABLE_READ() bool(READ(Y_ENABLE_PIN))
#if HAS_Y_AXIS
#ifndef Y_ENABLE_INIT
#define Y_ENABLE_INIT() SET_OUTPUT(Y_ENABLE_PIN)
#define Y_ENABLE_WRITE(STATE) WRITE(Y_ENABLE_PIN,STATE)
#define Y_ENABLE_READ() bool(READ(Y_ENABLE_PIN))
#endif
#ifndef Y_DIR_INIT
#define Y_DIR_INIT() SET_OUTPUT(Y_DIR_PIN)
#define Y_DIR_WRITE(STATE) WRITE(Y_DIR_PIN,STATE)
#define Y_DIR_READ() bool(READ(Y_DIR_PIN))
#endif
#define Y_STEP_INIT() SET_OUTPUT(Y_STEP_PIN)
#ifndef Y_STEP_WRITE
#define Y_STEP_WRITE(STATE) WRITE(Y_STEP_PIN,STATE)
#endif
#define Y_STEP_READ() bool(READ(Y_STEP_PIN))
#endif
#ifndef Y_DIR_INIT
#define Y_DIR_INIT() SET_OUTPUT(Y_DIR_PIN)
#define Y_DIR_WRITE(STATE) WRITE(Y_DIR_PIN,STATE)
#define Y_DIR_READ() bool(READ(Y_DIR_PIN))
#endif
#define Y_STEP_INIT() SET_OUTPUT(Y_STEP_PIN)
#ifndef Y_STEP_WRITE
#define Y_STEP_WRITE(STATE) WRITE(Y_STEP_PIN,STATE)
#endif
#define Y_STEP_READ() bool(READ(Y_STEP_PIN))
// Z Stepper
#ifndef Z_ENABLE_INIT
#define Z_ENABLE_INIT() SET_OUTPUT(Z_ENABLE_PIN)
#define Z_ENABLE_WRITE(STATE) WRITE(Z_ENABLE_PIN,STATE)
#define Z_ENABLE_READ() bool(READ(Z_ENABLE_PIN))
#if HAS_Z_AXIS
#ifndef Z_ENABLE_INIT
#define Z_ENABLE_INIT() SET_OUTPUT(Z_ENABLE_PIN)
#define Z_ENABLE_WRITE(STATE) WRITE(Z_ENABLE_PIN,STATE)
#define Z_ENABLE_READ() bool(READ(Z_ENABLE_PIN))
#endif
#ifndef Z_DIR_INIT
#define Z_DIR_INIT() SET_OUTPUT(Z_DIR_PIN)
#define Z_DIR_WRITE(STATE) WRITE(Z_DIR_PIN,STATE)
#define Z_DIR_READ() bool(READ(Z_DIR_PIN))
#endif
#define Z_STEP_INIT() SET_OUTPUT(Z_STEP_PIN)
#ifndef Z_STEP_WRITE
#define Z_STEP_WRITE(STATE) WRITE(Z_STEP_PIN,STATE)
#endif
#define Z_STEP_READ() bool(READ(Z_STEP_PIN))
#endif
#ifndef Z_DIR_INIT
#define Z_DIR_INIT() SET_OUTPUT(Z_DIR_PIN)
#define Z_DIR_WRITE(STATE) WRITE(Z_DIR_PIN,STATE)
#define Z_DIR_READ() bool(READ(Z_DIR_PIN))
#endif
#define Z_STEP_INIT() SET_OUTPUT(Z_STEP_PIN)
#ifndef Z_STEP_WRITE
#define Z_STEP_WRITE(STATE) WRITE(Z_STEP_PIN,STATE)
#endif
#define Z_STEP_READ() bool(READ(Z_STEP_PIN))
// X2 Stepper
#if HAS_X2_ENABLE
@@ -201,6 +205,63 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#define Z4_DIR_WRITE(STATE) NOOP
#endif
// I Stepper
#if LINEAR_AXES >= 4
#ifndef I_ENABLE_INIT
#define I_ENABLE_INIT() SET_OUTPUT(I_ENABLE_PIN)
#define I_ENABLE_WRITE(STATE) WRITE(I_ENABLE_PIN,STATE)
#define I_ENABLE_READ() bool(READ(I_ENABLE_PIN))
#endif
#ifndef I_DIR_INIT
#define I_DIR_INIT() SET_OUTPUT(I_DIR_PIN)
#define I_DIR_WRITE(STATE) WRITE(I_DIR_PIN,STATE)
#define I_DIR_READ() bool(READ(I_DIR_PIN))
#endif
#define I_STEP_INIT() SET_OUTPUT(I_STEP_PIN)
#ifndef I_STEP_WRITE
#define I_STEP_WRITE(STATE) WRITE(I_STEP_PIN,STATE)
#endif
#define I_STEP_READ() bool(READ(I_STEP_PIN))
#endif
// J Stepper
#if LINEAR_AXES >= 5
#ifndef J_ENABLE_INIT
#define J_ENABLE_INIT() SET_OUTPUT(J_ENABLE_PIN)
#define J_ENABLE_WRITE(STATE) WRITE(J_ENABLE_PIN,STATE)
#define J_ENABLE_READ() bool(READ(J_ENABLE_PIN))
#endif
#ifndef J_DIR_INIT
#define J_DIR_INIT() SET_OUTPUT(J_DIR_PIN)
#define J_DIR_WRITE(STATE) WRITE(J_DIR_PIN,STATE)
#define J_DIR_READ() bool(READ(J_DIR_PIN))
#endif
#define J_STEP_INIT() SET_OUTPUT(J_STEP_PIN)
#ifndef J_STEP_WRITE
#define J_STEP_WRITE(STATE) WRITE(J_STEP_PIN,STATE)
#endif
#define J_STEP_READ() bool(READ(J_STEP_PIN))
#endif
// K Stepper
#if LINEAR_AXES >= 6
#ifndef K_ENABLE_INIT
#define K_ENABLE_INIT() SET_OUTPUT(K_ENABLE_PIN)
#define K_ENABLE_WRITE(STATE) WRITE(K_ENABLE_PIN,STATE)
#define K_ENABLE_READ() bool(READ(K_ENABLE_PIN))
#endif
#ifndef K_DIR_INIT
#define K_DIR_INIT() SET_OUTPUT(K_DIR_PIN)
#define K_DIR_WRITE(STATE) WRITE(K_DIR_PIN,STATE)
#define K_DIR_READ() bool(READ(K_DIR_PIN))
#endif
#define K_STEP_INIT() SET_OUTPUT(K_STEP_PIN)
#ifndef K_STEP_WRITE
#define K_STEP_WRITE(STATE) WRITE(K_STEP_PIN,STATE)
#endif
#define K_STEP_READ() bool(READ(K_STEP_PIN))
#endif
// E0 Stepper
#ifndef E0_ENABLE_INIT
#define E0_ENABLE_INIT() SET_OUTPUT(E0_ENABLE_PIN)
@@ -417,12 +478,15 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(E ? INVERT_E0_DIR : !INVERT_E0_DIR); }while(0)
#define REV_E_DIR(E) do{ E0_DIR_WRITE(E ? !INVERT_E0_DIR : INVERT_E0_DIR); }while(0)
#endif
#elif ENABLED(PRUSA_MMU2)
#elif HAS_PRUSA_MMU2 // One multiplexed stepper driver
#define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
#define NORM_E_DIR(E) E0_DIR_WRITE(!INVERT_E0_DIR)
#define REV_E_DIR(E) E0_DIR_WRITE( INVERT_E0_DIR)
#elif ENABLED(MK2_MULTIPLEXER) // One multiplexed stepper driver, reversed on odd index
#elif HAS_PRUSA_MMU1 // One multiplexed stepper driver, reversed on odd index
#define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? !INVERT_E0_DIR: INVERT_E0_DIR); }while(0)
#define REV_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? INVERT_E0_DIR: !INVERT_E0_DIR); }while(0)
@@ -581,6 +645,11 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#endif
#elif ENABLED(E_DUAL_STEPPER_DRIVERS)
#define E_STEP_WRITE(E,V) do{ E0_STEP_WRITE(V); E1_STEP_WRITE(V); }while(0)
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E0_DIR ^ ENABLED(INVERT_E1_VS_E0_DIR)); }while(0)
#define REV_E_DIR(E) do{ E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E0_DIR ^ ENABLED(INVERT_E1_VS_E0_DIR)); }while(0)
#elif E_STEPPERS
#define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
#define NORM_E_DIR(E) E0_DIR_WRITE(!INVERT_E0_DIR)
@@ -598,138 +667,87 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
//
#ifndef ENABLE_STEPPER_X
#if HAS_X_ENABLE
#define ENABLE_STEPPER_X() X_ENABLE_WRITE( X_ENABLE_ON)
#else
#define ENABLE_STEPPER_X() NOOP
#endif
#define ENABLE_STEPPER_X() TERN(HAS_X_ENABLE, X_ENABLE_WRITE( X_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_X
#if HAS_X_ENABLE
#define DISABLE_STEPPER_X() X_ENABLE_WRITE(!X_ENABLE_ON)
#else
#define DISABLE_STEPPER_X() NOOP
#endif
#define DISABLE_STEPPER_X() TERN(HAS_X_ENABLE, X_ENABLE_WRITE(!X_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_X2
#if HAS_X2_ENABLE
#define ENABLE_STEPPER_X2() X2_ENABLE_WRITE( X_ENABLE_ON)
#else
#define ENABLE_STEPPER_X2() NOOP
#endif
#define ENABLE_STEPPER_X2() TERN(HAS_X2_ENABLE, X2_ENABLE_WRITE( X_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_X2
#if HAS_X2_ENABLE
#define DISABLE_STEPPER_X2() X2_ENABLE_WRITE(!X_ENABLE_ON)
#else
#define DISABLE_STEPPER_X2() NOOP
#endif
#define DISABLE_STEPPER_X2() TERN(HAS_X2_ENABLE, X2_ENABLE_WRITE(!X_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_Y
#if HAS_Y_ENABLE
#define ENABLE_STEPPER_Y() Y_ENABLE_WRITE( Y_ENABLE_ON)
#else
#define ENABLE_STEPPER_Y() NOOP
#endif
#define ENABLE_STEPPER_Y() TERN(HAS_Y_ENABLE, Y_ENABLE_WRITE( Y_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_Y
#if HAS_Y_ENABLE
#define DISABLE_STEPPER_Y() Y_ENABLE_WRITE(!Y_ENABLE_ON)
#else
#define DISABLE_STEPPER_Y() NOOP
#endif
#define DISABLE_STEPPER_Y() TERN(HAS_Y_ENABLE, Y_ENABLE_WRITE(!Y_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_Y2
#if HAS_Y2_ENABLE
#define ENABLE_STEPPER_Y2() Y2_ENABLE_WRITE( Y_ENABLE_ON)
#else
#define ENABLE_STEPPER_Y2() NOOP
#endif
#define ENABLE_STEPPER_Y2() TERN(HAS_Y2_ENABLE, Y2_ENABLE_WRITE( Y_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_Y2
#if HAS_Y2_ENABLE
#define DISABLE_STEPPER_Y2() Y2_ENABLE_WRITE(!Y_ENABLE_ON)
#else
#define DISABLE_STEPPER_Y2() NOOP
#endif
#define DISABLE_STEPPER_Y2() TERN(HAS_Y2_ENABLE, Y2_ENABLE_WRITE(!Y_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_Z
#if HAS_Z_ENABLE
#define ENABLE_STEPPER_Z() Z_ENABLE_WRITE( Z_ENABLE_ON)
#else
#define ENABLE_STEPPER_Z() NOOP
#endif
#define ENABLE_STEPPER_Z() TERN(HAS_Z_ENABLE, Z_ENABLE_WRITE( Z_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_Z
#if HAS_Z_ENABLE
#define DISABLE_STEPPER_Z() Z_ENABLE_WRITE(!Z_ENABLE_ON)
#else
#define DISABLE_STEPPER_Z() NOOP
#endif
#define DISABLE_STEPPER_Z() TERN(HAS_Z_ENABLE, Z_ENABLE_WRITE(!Z_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_Z2
#if HAS_Z2_ENABLE
#define ENABLE_STEPPER_Z2() Z2_ENABLE_WRITE( Z_ENABLE_ON)
#else
#define ENABLE_STEPPER_Z2() NOOP
#endif
#define ENABLE_STEPPER_Z2() TERN(HAS_Z2_ENABLE, Z2_ENABLE_WRITE( Z_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_Z2
#if HAS_Z2_ENABLE
#define DISABLE_STEPPER_Z2() Z2_ENABLE_WRITE(!Z_ENABLE_ON)
#else
#define DISABLE_STEPPER_Z2() NOOP
#endif
#define DISABLE_STEPPER_Z2() TERN(HAS_Z2_ENABLE, Z2_ENABLE_WRITE(!Z_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_Z3
#if HAS_Z3_ENABLE
#define ENABLE_STEPPER_Z3() Z3_ENABLE_WRITE( Z_ENABLE_ON)
#else
#define ENABLE_STEPPER_Z3() NOOP
#endif
#define ENABLE_STEPPER_Z3() TERN(HAS_Z3_ENABLE, Z3_ENABLE_WRITE( Z_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_Z3
#if HAS_Z3_ENABLE
#define DISABLE_STEPPER_Z3() Z3_ENABLE_WRITE(!Z_ENABLE_ON)
#else
#define DISABLE_STEPPER_Z3() NOOP
#endif
#define DISABLE_STEPPER_Z3() TERN(HAS_Z3_ENABLE, Z3_ENABLE_WRITE(!Z_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_Z4
#if HAS_Z4_ENABLE
#define ENABLE_STEPPER_Z4() Z4_ENABLE_WRITE( Z_ENABLE_ON)
#else
#define ENABLE_STEPPER_Z4() NOOP
#endif
#define ENABLE_STEPPER_Z4() TERN(HAS_Z4_ENABLE, Z4_ENABLE_WRITE( Z_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_Z4
#if HAS_Z4_ENABLE
#define DISABLE_STEPPER_Z4() Z4_ENABLE_WRITE(!Z_ENABLE_ON)
#else
#define DISABLE_STEPPER_Z4() NOOP
#endif
#define DISABLE_STEPPER_Z4() TERN(HAS_Z4_ENABLE, Z4_ENABLE_WRITE(!Z_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_I
#define ENABLE_STEPPER_I() TERN(HAS_I_ENABLE, I_ENABLE_WRITE( I_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_I
#define DISABLE_STEPPER_I() TERN(HAS_I_ENABLE, I_ENABLE_WRITE(!I_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_J
#define ENABLE_STEPPER_J() TERN(HAS_J_ENABLE, J_ENABLE_WRITE( J_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_J
#define DISABLE_STEPPER_J() TERN(HAS_J_ENABLE, J_ENABLE_WRITE(!J_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_K
#define ENABLE_STEPPER_K() TERN(HAS_K_ENABLE, K_ENABLE_WRITE( K_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_K
#define DISABLE_STEPPER_K() TERN(HAS_K_ENABLE, K_ENABLE_WRITE(!K_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_E0
#if HAS_E0_ENABLE
#define ENABLE_STEPPER_E0() E0_ENABLE_WRITE( E_ENABLE_ON)
#else
#define ENABLE_STEPPER_E0() NOOP
#endif
#define ENABLE_STEPPER_E0() TERN(HAS_E0_ENABLE, E0_ENABLE_WRITE( E_ENABLE_ON), NOOP)
#endif
#ifndef DISABLE_STEPPER_E0
#if HAS_E0_ENABLE
#define DISABLE_STEPPER_E0() E0_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define DISABLE_STEPPER_E0() NOOP
#endif
#define DISABLE_STEPPER_E0() TERN(HAS_E0_ENABLE, E0_ENABLE_WRITE(!E_ENABLE_ON), NOOP)
#endif
#ifndef ENABLE_STEPPER_E1
@@ -840,21 +858,71 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
//
// Axis steppers enable / disable macros
//
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
// Avoid expensive calls to enable / disable steppers
extern xyz_bool_t axis_sw_enabled;
#define SHOULD_ENABLE(N) !axis_sw_enabled.N
#define SHOULD_DISABLE(N) axis_sw_enabled.N
#define AFTER_CHANGE(N,TF) axis_sw_enabled.N = TF
#else
#define SHOULD_ENABLE(N) true
#define SHOULD_DISABLE(N) true
#define AFTER_CHANGE(N,TF) NOOP
#endif
#define ENABLE_AXIS_X() do{ ENABLE_STEPPER_X(); ENABLE_STEPPER_X2(); }while(0)
#define DISABLE_AXIS_X() do{ DISABLE_STEPPER_X(); DISABLE_STEPPER_X2(); CBI(axis_known_position, X_AXIS); }while(0)
#define ENABLE_AXIS_X() if (SHOULD_ENABLE(x)) { ENABLE_STEPPER_X(); ENABLE_STEPPER_X2(); AFTER_CHANGE(x, true); }
#define DISABLE_AXIS_X() if (SHOULD_DISABLE(x)) { DISABLE_STEPPER_X(); DISABLE_STEPPER_X2(); AFTER_CHANGE(x, false); set_axis_untrusted(X_AXIS); }
#define ENABLE_AXIS_Y() do{ ENABLE_STEPPER_Y(); ENABLE_STEPPER_Y2(); }while(0)
#define DISABLE_AXIS_Y() do{ DISABLE_STEPPER_Y(); DISABLE_STEPPER_Y2(); CBI(axis_known_position, Y_AXIS); }while(0)
#if HAS_Y_AXIS
#define ENABLE_AXIS_Y() if (SHOULD_ENABLE(y)) { ENABLE_STEPPER_Y(); ENABLE_STEPPER_Y2(); AFTER_CHANGE(y, true); }
#define DISABLE_AXIS_Y() if (SHOULD_DISABLE(y)) { DISABLE_STEPPER_Y(); DISABLE_STEPPER_Y2(); AFTER_CHANGE(y, false); set_axis_untrusted(Y_AXIS); }
#else
#define ENABLE_AXIS_Y() NOOP
#define DISABLE_AXIS_Y() NOOP
#endif
#define ENABLE_AXIS_Z() do{ ENABLE_STEPPER_Z(); ENABLE_STEPPER_Z2(); ENABLE_STEPPER_Z3(); ENABLE_STEPPER_Z4(); }while(0)
#define DISABLE_AXIS_Z() do{ DISABLE_STEPPER_Z(); DISABLE_STEPPER_Z2(); DISABLE_STEPPER_Z3(); DISABLE_STEPPER_Z4(); CBI(axis_known_position, Z_AXIS); }while(0)
#if HAS_Z_AXIS
#define ENABLE_AXIS_Z() if (SHOULD_ENABLE(z)) { ENABLE_STEPPER_Z(); ENABLE_STEPPER_Z2(); ENABLE_STEPPER_Z3(); ENABLE_STEPPER_Z4(); AFTER_CHANGE(z, true); }
#define DISABLE_AXIS_Z() if (SHOULD_DISABLE(z)) { DISABLE_STEPPER_Z(); DISABLE_STEPPER_Z2(); DISABLE_STEPPER_Z3(); DISABLE_STEPPER_Z4(); AFTER_CHANGE(z, false); set_axis_untrusted(Z_AXIS); Z_RESET(); }
#else
#define ENABLE_AXIS_Z() NOOP
#define DISABLE_AXIS_Z() NOOP
#endif
#ifdef Z_IDLE_HEIGHT
#define Z_RESET() do{ current_position.z = Z_IDLE_HEIGHT; sync_plan_position(); }while(0)
#else
#define Z_RESET()
#endif
#if LINEAR_AXES >= 4
#define ENABLE_AXIS_I() if (SHOULD_ENABLE(i)) { ENABLE_STEPPER_I(); AFTER_CHANGE(i, true); }
#define DISABLE_AXIS_I() if (SHOULD_DISABLE(i)) { DISABLE_STEPPER_I(); AFTER_CHANGE(i, false); set_axis_untrusted(I_AXIS); }
#else
#define ENABLE_AXIS_I() NOOP
#define DISABLE_AXIS_I() NOOP
#endif
#if LINEAR_AXES >= 5
#define ENABLE_AXIS_J() if (SHOULD_ENABLE(j)) { ENABLE_STEPPER_J(); AFTER_CHANGE(j, true); }
#define DISABLE_AXIS_J() if (SHOULD_DISABLE(j)) { DISABLE_STEPPER_J(); AFTER_CHANGE(j, false); set_axis_untrusted(J_AXIS); }
#else
#define ENABLE_AXIS_J() NOOP
#define DISABLE_AXIS_J() NOOP
#endif
#if LINEAR_AXES >= 6
#define ENABLE_AXIS_K() if (SHOULD_ENABLE(k)) { ENABLE_STEPPER_K(); AFTER_CHANGE(k, true); }
#define DISABLE_AXIS_K() if (SHOULD_DISABLE(k)) { DISABLE_STEPPER_K(); AFTER_CHANGE(k, false); set_axis_untrusted(K_AXIS); }
#else
#define ENABLE_AXIS_K() NOOP
#define DISABLE_AXIS_K() NOOP
#endif
//
// Extruder steppers enable / disable macros
//
#if ENABLED(MIXING_EXTRUDER)
/**
* Mixing steppers keep all their enable (and direction) states synchronized
*/
@@ -862,17 +930,23 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
#define _CALL_DIS_E(N) DISABLE_STEPPER_E##N () ;
#define ENABLE_AXIS_E0() { RREPEAT(MIXING_STEPPERS, _CALL_ENA_E) }
#define DISABLE_AXIS_E0() { RREPEAT(MIXING_STEPPERS, _CALL_DIS_E) }
#elif ENABLED(E_DUAL_STEPPER_DRIVERS)
#define ENABLE_AXIS_E0() do{ ENABLE_STEPPER_E0(); ENABLE_STEPPER_E1(); }while(0)
#define DISABLE_AXIS_E0() do{ DISABLE_STEPPER_E0(); DISABLE_STEPPER_E1(); }while(0)
#endif
#ifndef ENABLE_AXIS_E0
#if E_STEPPERS > 0 && HAS_E0_ENABLE
#if E_STEPPERS && HAS_E0_ENABLE
#define ENABLE_AXIS_E0() ENABLE_STEPPER_E0()
#else
#define ENABLE_AXIS_E0() NOOP
#endif
#endif
#ifndef DISABLE_AXIS_E0
#if E_STEPPERS > 0 && HAS_E0_ENABLE
#if E_STEPPERS && HAS_E0_ENABLE
#define DISABLE_AXIS_E0() DISABLE_STEPPER_E0()
#else
#define DISABLE_AXIS_E0() NOOP

554
Marlin/src/module/stepper/trinamic.cpp Executable file → Normal file
View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@@ -35,8 +35,10 @@
#include <HardwareSerial.h>
#include <SPI.h>
enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
#define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX])
enum StealthIndex : uint8_t {
LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K)
};
#define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE)
// IC = TMC model number
// ST = Stepper object letter
@@ -49,8 +51,12 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
#define __TMC_SPI_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_CS_PIN, float(ST##_RSENSE), ST##_CHAIN_POS)
#endif
#define TMC_UART_HW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(&ST##_HARDWARE_SERIAL, float(ST##_RSENSE), ST##_SLAVE_ADDRESS)
#define TMC_UART_SW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_SERIAL_RX_PIN, ST##_SERIAL_TX_PIN, float(ST##_RSENSE), ST##_SLAVE_ADDRESS, ST##_SERIAL_RX_PIN > -1)
#if ENABLED(TMC_SERIAL_MULTIPLEXER)
#define TMC_UART_HW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(&ST##_HARDWARE_SERIAL, float(ST##_RSENSE), ST##_SLAVE_ADDRESS, SERIAL_MUL_PIN1, SERIAL_MUL_PIN2)
#else
#define TMC_UART_HW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(&ST##_HARDWARE_SERIAL, float(ST##_RSENSE), ST##_SLAVE_ADDRESS)
#endif
#define TMC_UART_SW_DEFINE(IC, ST, L, AI) TMCMarlin<IC##Stepper, L, AI> stepper##ST(ST##_SERIAL_RX_PIN, ST##_SERIAL_TX_PIN, float(ST##_RSENSE), ST##_SLAVE_ADDRESS)
#define _TMC_SPI_DEFINE(IC, ST, AI) __TMC_SPI_DEFINE(IC, ST, TMC_##ST##_LABEL, AI)
#define TMC_SPI_DEFINE(ST, AI) _TMC_SPI_DEFINE(ST##_DRIVER_TYPE, ST, AI##_AXIS)
@@ -58,7 +64,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
#define _TMC_UART_DEFINE(SWHW, IC, ST, AI) TMC_UART_##SWHW##_DEFINE(IC, ST, TMC_##ST##_LABEL, AI)
#define TMC_UART_DEFINE(SWHW, ST, AI) _TMC_UART_DEFINE(SWHW, ST##_DRIVER_TYPE, ST, AI##_AXIS)
#if ENABLED(DISTINCT_E_FACTORS) && E_STEPPERS > 1
#if ENABLED(DISTINCT_E_FACTORS)
#define TMC_SPI_DEFINE_E(AI) TMC_SPI_DEFINE(E##AI, E##AI)
#define TMC_UART_DEFINE_E(SWHW, AI) TMC_UART_DEFINE(SWHW, E##AI, E##AI)
#else
@@ -91,6 +97,15 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
#if AXIS_HAS_SPI(Z4)
TMC_SPI_DEFINE(Z4, Z);
#endif
#if AXIS_HAS_SPI(I)
TMC_SPI_DEFINE(I, I);
#endif
#if AXIS_HAS_SPI(J)
TMC_SPI_DEFINE(J, J);
#endif
#if AXIS_HAS_SPI(K)
TMC_SPI_DEFINE(K, K);
#endif
#if AXIS_HAS_SPI(E0)
TMC_SPI_DEFINE_E(0);
#endif
@@ -117,32 +132,84 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
#endif
#ifndef TMC_BAUD_RATE
#if HAS_TMC_SW_SERIAL
// Reduce baud rate for boards not already overriding TMC_BAUD_RATE for software serial.
// Testing has shown that 115200 is not 100% reliable on AVR platforms, occasionally
// failing to read status properly. 32-bit platforms typically define an even lower
// TMC_BAUD_RATE, due to differences in how SoftwareSerial libraries work on different
// platforms.
#define TMC_BAUD_RATE 57600
#else
#define TMC_BAUD_RATE 115200
#endif
// Reduce baud rate for boards not already overriding TMC_BAUD_RATE for software serial.
// Testing has shown that 115200 is not 100% reliable on AVR platforms, occasionally
// failing to read status properly. 32-bit platforms typically define an even lower
// TMC_BAUD_RATE, due to differences in how SoftwareSerial libraries work on different
// platforms.
#define TMC_BAUD_RATE TERN(HAS_TMC_SW_SERIAL, 57600, 115200)
#endif
#ifndef TMC_X_BAUD_RATE
#define TMC_X_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_X2_BAUD_RATE
#define TMC_X2_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_Y_BAUD_RATE
#define TMC_Y_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_Y2_BAUD_RATE
#define TMC_Y2_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_Z_BAUD_RATE
#define TMC_Z_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_Z2_BAUD_RATE
#define TMC_Z2_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_Z3_BAUD_RATE
#define TMC_Z3_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_Z4_BAUD_RATE
#define TMC_Z4_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_I_BAUD_RATE
#define TMC_I_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_J_BAUD_RATE
#define TMC_J_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_K_BAUD_RATE
#define TMC_K_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_E0_BAUD_RATE
#define TMC_E0_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_E1_BAUD_RATE
#define TMC_E1_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_E2_BAUD_RATE
#define TMC_E2_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_E3_BAUD_RATE
#define TMC_E3_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_E4_BAUD_RATE
#define TMC_E4_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_E5_BAUD_RATE
#define TMC_E5_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_E6_BAUD_RATE
#define TMC_E6_BAUD_RATE TMC_BAUD_RATE
#endif
#ifndef TMC_E7_BAUD_RATE
#define TMC_E7_BAUD_RATE TMC_BAUD_RATE
#endif
#if HAS_DRIVER(TMC2130)
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
void tmc_init(TMCMarlin<TMC2130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
void tmc_init(TMCMarlin<TMC2130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
st.begin();
CHOPCONF_t chopconf{0};
chopconf.tbl = 1;
chopconf.toff = chopper_timing.toff;
chopconf.intpol = INTERPOLATE;
chopconf.hend = chopper_timing.hend + 3;
chopconf.hstrt = chopper_timing.hstrt - 1;
#if ENABLED(SQUARE_WAVE_STEPPING)
chopconf.dedge = true;
#endif
chopconf.tbl = 0b01;
chopconf.toff = chop_init.toff;
chopconf.intpol = interpolate;
chopconf.hend = chop_init.hend + 3;
chopconf.hstrt = chop_init.hstrt - 1;
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
st.CHOPCONF(chopconf.sr);
st.rms_current(mA, HOLD_MULTIPLIER);
@@ -160,11 +227,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
pwmconf.pwm_ampl = 180;
st.PWMCONF(pwmconf.sr);
#if ENABLED(HYBRID_THRESHOLD)
st.set_pwm_thrs(hyb_thrs);
#else
UNUSED(hyb_thrs);
#endif
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
st.GSTAT(); // Clear GSTAT
}
@@ -172,18 +235,16 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
#if HAS_DRIVER(TMC2160)
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
void tmc_init(TMCMarlin<TMC2160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
void tmc_init(TMCMarlin<TMC2160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
st.begin();
CHOPCONF_t chopconf{0};
chopconf.tbl = 1;
chopconf.toff = chopper_timing.toff;
chopconf.intpol = INTERPOLATE;
chopconf.hend = chopper_timing.hend + 3;
chopconf.hstrt = chopper_timing.hstrt - 1;
#if ENABLED(SQUARE_WAVE_STEPPING)
chopconf.dedge = true;
#endif
chopconf.tbl = 0b01;
chopconf.toff = chop_init.toff;
chopconf.intpol = interpolate;
chopconf.hend = chop_init.hend + 3;
chopconf.hstrt = chop_init.hstrt - 1;
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
st.CHOPCONF(chopconf.sr);
st.rms_current(mA, HOLD_MULTIPLIER);
@@ -204,11 +265,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
pwmconf.pwm_ofs = 36;
st.PWMCONF(pwmconf.sr);
#if ENABLED(HYBRID_THRESHOLD)
st.set_pwm_thrs(hyb_thrs);
#else
UNUSED(hyb_thrs);
#endif
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
st.GSTAT(); // Clear GSTAT
}
@@ -221,225 +278,323 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
#if AXIS_HAS_UART(X)
#ifdef X_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, X, X);
#define X_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, X, X);
#define X_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(X2)
#ifdef X2_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, X2, X);
#define X2_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, X2, X);
#define X2_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(Y)
#ifdef Y_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, Y, Y);
#define Y_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, Y, Y);
#define Y_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(Y2)
#ifdef Y2_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, Y2, Y);
#define Y2_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, Y2, Y);
#define Y2_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(Z)
#ifdef Z_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, Z, Z);
#define Z_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, Z, Z);
#define Z_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(Z2)
#ifdef Z2_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, Z2, Z);
#define Z2_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, Z2, Z);
#define Z2_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(Z3)
#ifdef Z3_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, Z3, Z);
#define Z3_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, Z3, Z);
#define Z3_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(Z4)
#ifdef Z4_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, Z4, Z);
#define Z4_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, Z4, Z);
#define Z4_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(I)
#ifdef I_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, I, I);
#define I_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, I, I);
#define I_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(J)
#ifdef J_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, J, J);
#define J_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, J, J);
#define J_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(K)
#ifdef K_HARDWARE_SERIAL
TMC_UART_DEFINE(HW, K, K);
#define K_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE(SW, K, K);
#define K_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(E0)
#ifdef E0_HARDWARE_SERIAL
TMC_UART_DEFINE_E(HW, 0);
#define E0_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE_E(SW, 0);
#define E0_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(E1)
#ifdef E1_HARDWARE_SERIAL
TMC_UART_DEFINE_E(HW, 1);
#define E1_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE_E(SW, 1);
#define E1_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(E2)
#ifdef E2_HARDWARE_SERIAL
TMC_UART_DEFINE_E(HW, 2);
#define E2_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE_E(SW, 2);
#define E2_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(E3)
#ifdef E3_HARDWARE_SERIAL
TMC_UART_DEFINE_E(HW, 3);
#define E3_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE_E(SW, 3);
#define E3_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(E4)
#ifdef E4_HARDWARE_SERIAL
TMC_UART_DEFINE_E(HW, 4);
#define E4_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE_E(SW, 4);
#define E4_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(E5)
#ifdef E5_HARDWARE_SERIAL
TMC_UART_DEFINE_E(HW, 5);
#define E5_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE_E(SW, 5);
#define E5_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(E6)
#ifdef E6_HARDWARE_SERIAL
TMC_UART_DEFINE_E(HW, 6);
#define E6_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE_E(SW, 6);
#define E6_HAS_SW_SERIAL 1
#endif
#endif
#if AXIS_HAS_UART(E7)
#ifdef E7_HARDWARE_SERIAL
TMC_UART_DEFINE_E(HW, 7);
#define E7_HAS_HW_SERIAL 1
#else
TMC_UART_DEFINE_E(SW, 7);
#define E7_HAS_SW_SERIAL 1
#endif
#endif
#define _EN_ITEM(N) , E##N
enum TMCAxis : uint8_t { LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL };
#undef _EN_ITEM
void tmc_serial_begin() {
#if HAS_TMC_HW_SERIAL
struct {
const void *ptr[TMCAxis::TOTAL];
bool began(const TMCAxis a, const void * const p) {
LOOP_L_N(i, a) if (p == ptr[i]) return true;
ptr[a] = p; return false;
};
} sp_helper;
#define HW_SERIAL_BEGIN(A) do{ if (!sp_helper.began(TMCAxis::A, &A##_HARDWARE_SERIAL)) \
A##_HARDWARE_SERIAL.begin(TMC_##A##_BAUD_RATE); }while(0)
#endif
#if AXIS_HAS_UART(X)
#ifdef X_HARDWARE_SERIAL
X_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(X);
#else
stepperX.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(X2)
#ifdef X2_HARDWARE_SERIAL
X2_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(X2);
#else
stepperX2.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(Y)
#ifdef Y_HARDWARE_SERIAL
Y_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(Y);
#else
stepperY.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(Y2)
#ifdef Y2_HARDWARE_SERIAL
Y2_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(Y2);
#else
stepperY2.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(Z)
#ifdef Z_HARDWARE_SERIAL
Z_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(Z);
#else
stepperZ.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(Z2)
#ifdef Z2_HARDWARE_SERIAL
Z2_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(Z2);
#else
stepperZ2.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(Z3)
#ifdef Z3_HARDWARE_SERIAL
Z3_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(Z3);
#else
stepperZ3.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(Z4)
#ifdef Z4_HARDWARE_SERIAL
Z4_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(Z4);
#else
stepperZ4.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(I)
#ifdef I_HARDWARE_SERIAL
HW_SERIAL_BEGIN(I);
#else
stepperI.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(J)
#ifdef J_HARDWARE_SERIAL
HW_SERIAL_BEGIN(J);
#else
stepperJ.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(K)
#ifdef K_HARDWARE_SERIAL
HW_SERIAL_BEGIN(K);
#else
stepperK.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(E0)
#ifdef E0_HARDWARE_SERIAL
E0_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(E0);
#else
stepperE0.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(E1)
#ifdef E1_HARDWARE_SERIAL
E1_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(E1);
#else
stepperE1.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(E2)
#ifdef E2_HARDWARE_SERIAL
E2_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(E2);
#else
stepperE2.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(E3)
#ifdef E3_HARDWARE_SERIAL
E3_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(E3);
#else
stepperE3.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(E4)
#ifdef E4_HARDWARE_SERIAL
E4_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(E4);
#else
stepperE4.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(E5)
#ifdef E5_HARDWARE_SERIAL
E5_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(E5);
#else
stepperE5.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(E6)
#ifdef E6_HARDWARE_SERIAL
E6_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(E6);
#else
stepperE6.beginSerial(TMC_BAUD_RATE);
#endif
#endif
#if AXIS_HAS_UART(E7)
#ifdef E7_HARDWARE_SERIAL
E7_HARDWARE_SERIAL.begin(TMC_BAUD_RATE);
HW_SERIAL_BEGIN(E7);
#else
stepperE7.beginSerial(TMC_BAUD_RATE);
#endif
@@ -449,7 +604,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
#if HAS_DRIVER(TMC2208)
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
void tmc_init(TMCMarlin<TMC2208Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
void tmc_init(TMCMarlin<TMC2208Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
TMC2208_n::GCONF_t gconf{0};
gconf.pdn_disable = true; // Use UART
gconf.mstep_reg_select = true; // Select microsteps with UART
@@ -460,13 +615,11 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
TMC2208_n::CHOPCONF_t chopconf{0};
chopconf.tbl = 0b01; // blank_time = 24
chopconf.toff = chopper_timing.toff;
chopconf.intpol = INTERPOLATE;
chopconf.hend = chopper_timing.hend + 3;
chopconf.hstrt = chopper_timing.hstrt - 1;
#if ENABLED(SQUARE_WAVE_STEPPING)
chopconf.dedge = true;
#endif
chopconf.toff = chop_init.toff;
chopconf.intpol = interpolate;
chopconf.hend = chop_init.hend + 3;
chopconf.hstrt = chop_init.hstrt - 1;
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
st.CHOPCONF(chopconf.sr);
st.rms_current(mA, HOLD_MULTIPLIER);
@@ -484,11 +637,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
pwmconf.pwm_ofs = 36;
st.PWMCONF(pwmconf.sr);
#if ENABLED(HYBRID_THRESHOLD)
st.set_pwm_thrs(hyb_thrs);
#else
UNUSED(hyb_thrs);
#endif
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
st.GSTAT(0b111); // Clear
delay(200);
@@ -497,7 +646,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
#if HAS_DRIVER(TMC2209)
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
void tmc_init(TMCMarlin<TMC2209Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
void tmc_init(TMCMarlin<TMC2209Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
TMC2208_n::GCONF_t gconf{0};
gconf.pdn_disable = true; // Use UART
gconf.mstep_reg_select = true; // Select microsteps with UART
@@ -508,13 +657,11 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
TMC2208_n::CHOPCONF_t chopconf{0};
chopconf.tbl = 0b01; // blank_time = 24
chopconf.toff = chopper_timing.toff;
chopconf.intpol = INTERPOLATE;
chopconf.hend = chopper_timing.hend + 3;
chopconf.hstrt = chopper_timing.hstrt - 1;
#if ENABLED(SQUARE_WAVE_STEPPING)
chopconf.dedge = true;
#endif
chopconf.toff = chop_init.toff;
chopconf.intpol = interpolate;
chopconf.hend = chop_init.hend + 3;
chopconf.hstrt = chop_init.hstrt - 1;
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
st.CHOPCONF(chopconf.sr);
st.rms_current(mA, HOLD_MULTIPLIER);
@@ -532,11 +679,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
pwmconf.pwm_ofs = 36;
st.PWMCONF(pwmconf.sr);
#if ENABLED(HYBRID_THRESHOLD)
st.set_pwm_thrs(hyb_thrs);
#else
UNUSED(hyb_thrs);
#endif
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
st.GSTAT(0b111); // Clear
delay(200);
@@ -545,45 +688,38 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
#if HAS_DRIVER(TMC2660)
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
void tmc_init(TMCMarlin<TMC2660Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t, const bool) {
void tmc_init(TMCMarlin<TMC2660Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t, const bool, const chopper_timing_t &chop_init, const bool interpolate) {
st.begin();
TMC2660_n::CHOPCONF_t chopconf{0};
chopconf.tbl = 1;
chopconf.toff = chopper_timing.toff;
chopconf.hend = chopper_timing.hend + 3;
chopconf.hstrt = chopper_timing.hstrt - 1;
chopconf.tbl = 0b01;
chopconf.toff = chop_init.toff;
chopconf.hend = chop_init.hend + 3;
chopconf.hstrt = chop_init.hstrt - 1;
st.CHOPCONF(chopconf.sr);
st.sdoff(0);
st.rms_current(mA);
st.microsteps(microsteps);
#if ENABLED(SQUARE_WAVE_STEPPING)
st.dedge(true);
#endif
st.intpol(INTERPOLATE);
TERN_(SQUARE_WAVE_STEPPING, st.dedge(true));
st.intpol(interpolate);
st.diss2g(true); // Disable short to ground protection. Too many false readings?
#if ENABLED(TMC_DEBUG)
st.rdsel(0b01);
#endif
TERN_(TMC_DEBUG, st.rdsel(0b01));
}
#endif // TMC2660
#if HAS_DRIVER(TMC5130)
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
void tmc_init(TMCMarlin<TMC5130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
void tmc_init(TMCMarlin<TMC5130Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
st.begin();
CHOPCONF_t chopconf{0};
chopconf.tbl = 1;
chopconf.toff = chopper_timing.toff;
chopconf.intpol = INTERPOLATE;
chopconf.hend = chopper_timing.hend + 3;
chopconf.hstrt = chopper_timing.hstrt - 1;
#if ENABLED(SQUARE_WAVE_STEPPING)
chopconf.dedge = true;
#endif
chopconf.tbl = 0b01;
chopconf.toff = chop_init.toff;
chopconf.intpol = interpolate;
chopconf.hend = chop_init.hend + 3;
chopconf.hstrt = chop_init.hstrt - 1;
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
st.CHOPCONF(chopconf.sr);
st.rms_current(mA, HOLD_MULTIPLIER);
@@ -601,11 +737,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
pwmconf.pwm_ampl = 180;
st.PWMCONF(pwmconf.sr);
#if ENABLED(HYBRID_THRESHOLD)
st.set_pwm_thrs(hyb_thrs);
#else
UNUSED(hyb_thrs);
#endif
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
st.GSTAT(); // Clear GSTAT
}
@@ -613,18 +745,16 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
#if HAS_DRIVER(TMC5160)
template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
void tmc_init(TMCMarlin<TMC5160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth) {
void tmc_init(TMCMarlin<TMC5160Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> &st, const uint16_t mA, const uint16_t microsteps, const uint32_t hyb_thrs, const bool stealth, const chopper_timing_t &chop_init, const bool interpolate) {
st.begin();
CHOPCONF_t chopconf{0};
chopconf.tbl = 1;
chopconf.toff = chopper_timing.toff;
chopconf.intpol = INTERPOLATE;
chopconf.hend = chopper_timing.hend + 3;
chopconf.hstrt = chopper_timing.hstrt - 1;
#if ENABLED(SQUARE_WAVE_STEPPING)
chopconf.dedge = true;
#endif
chopconf.tbl = 0b01;
chopconf.toff = chop_init.toff;
chopconf.intpol = interpolate;
chopconf.hend = chop_init.hend + 3;
chopconf.hstrt = chop_init.hstrt - 1;
TERN_(SQUARE_WAVE_STEPPING, chopconf.dedge = true);
st.CHOPCONF(chopconf.sr);
st.rms_current(mA, HOLD_MULTIPLIER);
@@ -645,11 +775,7 @@ enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
pwmconf.pwm_ofs = 36;
st.PWMCONF(pwmconf.sr);
#if ENABLED(HYBRID_THRESHOLD)
st.set_pwm_thrs(hyb_thrs);
#else
UNUSED(hyb_thrs);
#endif
TERN(HYBRID_THRESHOLD, st.set_pwm_thrs(hyb_thrs), UNUSED(hyb_thrs));
st.GSTAT(); // Clear GSTAT
}
#endif // TMC5160
@@ -679,6 +805,15 @@ void restore_trinamic_drivers() {
#if AXIS_IS_TMC(Z4)
stepperZ4.push();
#endif
#if AXIS_IS_TMC(I)
stepperI.push();
#endif
#if AXIS_IS_TMC(J)
stepperJ.push();
#endif
#if AXIS_IS_TMC(K)
stepperK.push();
#endif
#if AXIS_IS_TMC(E0)
stepperE0.push();
#endif
@@ -706,37 +841,23 @@ void restore_trinamic_drivers() {
}
void reset_trinamic_drivers() {
static constexpr bool stealthchop_by_axis[] = {
#if ENABLED(STEALTHCHOP_XY)
true
#else
false
#endif
,
#if ENABLED(STEALTHCHOP_Z)
true
#else
false
#endif
,
#if ENABLED(STEALTHCHOP_E)
true
#else
false
#endif
};
static constexpr bool stealthchop_by_axis[] = LOGICAL_AXIS_ARRAY(
ENABLED(STEALTHCHOP_E),
ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_Z),
ENABLED(STEALTHCHOP_I), ENABLED(STEALTHCHOP_J), ENABLED(STEALTHCHOP_K)
);
#if AXIS_IS_TMC(X)
TMC_INIT(X, STEALTH_AXIS_XY);
TMC_INIT(X, STEALTH_AXIS_X);
#endif
#if AXIS_IS_TMC(X2)
TMC_INIT(X2, STEALTH_AXIS_XY);
TMC_INIT(X2, STEALTH_AXIS_X);
#endif
#if AXIS_IS_TMC(Y)
TMC_INIT(Y, STEALTH_AXIS_XY);
TMC_INIT(Y, STEALTH_AXIS_Y);
#endif
#if AXIS_IS_TMC(Y2)
TMC_INIT(Y2, STEALTH_AXIS_XY);
TMC_INIT(Y2, STEALTH_AXIS_Y);
#endif
#if AXIS_IS_TMC(Z)
TMC_INIT(Z, STEALTH_AXIS_Z);
@@ -750,6 +871,15 @@ void reset_trinamic_drivers() {
#if AXIS_IS_TMC(Z4)
TMC_INIT(Z4, STEALTH_AXIS_Z);
#endif
#if AXIS_IS_TMC(I)
TMC_INIT(I, STEALTH_AXIS_I);
#endif
#if AXIS_IS_TMC(J)
TMC_INIT(J, STEALTH_AXIS_J);
#endif
#if AXIS_IS_TMC(K)
TMC_INIT(K, STEALTH_AXIS_K);
#endif
#if AXIS_IS_TMC(E0)
TMC_INIT(E0, STEALTH_AXIS_E);
#endif
@@ -777,39 +907,48 @@ void reset_trinamic_drivers() {
#if USE_SENSORLESS
#if X_SENSORLESS
#if AXIS_HAS_STALLGUARD(X)
stepperX.homing_threshold(X_STALL_SENSITIVITY);
stepperX.homing_threshold(X_STALL_SENSITIVITY);
#if AXIS_HAS_STALLGUARD(X2)
stepperX2.homing_threshold(CAT(TERN(X2_SENSORLESS, X2, X), _STALL_SENSITIVITY));
#endif
#if AXIS_HAS_STALLGUARD(X2) && !X2_SENSORLESS
stepperX2.homing_threshold(X_STALL_SENSITIVITY);
#endif
#endif
#if X2_SENSORLESS
stepperX2.homing_threshold(X2_STALL_SENSITIVITY);
#endif
#if Y_SENSORLESS
#if AXIS_HAS_STALLGUARD(Y)
stepperY.homing_threshold(Y_STALL_SENSITIVITY);
#endif
stepperY.homing_threshold(Y_STALL_SENSITIVITY);
#if AXIS_HAS_STALLGUARD(Y2)
stepperY2.homing_threshold(Y_STALL_SENSITIVITY);
stepperY2.homing_threshold(CAT(TERN(Y2_SENSORLESS, Y2, Y), _STALL_SENSITIVITY));
#endif
#endif
#if Z_SENSORLESS
#if AXIS_HAS_STALLGUARD(Z)
stepperZ.homing_threshold(Z_STALL_SENSITIVITY);
#endif
stepperZ.homing_threshold(Z_STALL_SENSITIVITY);
#if AXIS_HAS_STALLGUARD(Z2)
stepperZ2.homing_threshold(Z_STALL_SENSITIVITY);
stepperZ2.homing_threshold(CAT(TERN(Z2_SENSORLESS, Z2, Z), _STALL_SENSITIVITY));
#endif
#if AXIS_HAS_STALLGUARD(Z3)
stepperZ3.homing_threshold(Z_STALL_SENSITIVITY);
stepperZ3.homing_threshold(CAT(TERN(Z3_SENSORLESS, Z3, Z), _STALL_SENSITIVITY));
#endif
#if AXIS_HAS_STALLGUARD(Z4)
stepperZ4.homing_threshold(Z_STALL_SENSITIVITY);
stepperZ4.homing_threshold(CAT(TERN(Z4_SENSORLESS, Z4, Z), _STALL_SENSITIVITY));
#endif
#endif
#endif
#if I_SENSORLESS
stepperI.homing_threshold(I_STALL_SENSITIVITY);
#if AXIS_HAS_STALLGUARD(I)
stepperI.homing_threshold(CAT(TERN(I_SENSORLESS, I, I), _STALL_SENSITIVITY));
#endif
#endif
#if J_SENSORLESS
stepperJ.homing_threshold(J_STALL_SENSITIVITY);
#if AXIS_HAS_STALLGUARD(J)
stepperJ.homing_threshold(CAT(TERN(J_SENSORLESS, J, J), _STALL_SENSITIVITY));
#endif
#endif
#if K_SENSORLESS
stepperK.homing_threshold(K_STALL_SENSITIVITY);
#if AXIS_HAS_STALLGUARD(K)
stepperK.homing_threshold(CAT(TERN(K_SENSORLESS, K, K), _STALL_SENSITIVITY));
#endif
#endif
#endif // USE SENSORLESS
#ifdef TMC_ADV
TMC_ADV()
@@ -818,4 +957,81 @@ void reset_trinamic_drivers() {
stepper.set_directions();
}
// TMC Slave Address Conflict Detection
//
// Conflict detection is performed in the following way. Similar methods are used for
// hardware and software serial, but the implementations are independent.
//
// 1. Populate a data structure with UART parameters and addresses for all possible axis.
// If an axis is not in use, populate it with recognizable placeholder data.
// 2. For each axis in use, static_assert using a constexpr function, which counts the
// number of matching/conflicting axis. If the value is not exactly 1, fail.
#if ANY_AXIS_HAS(HW_SERIAL)
// Hardware serial names are compared as strings, since actually resolving them cannot occur in a constexpr.
// Using a fixed-length character array for the port name allows this to be constexpr compatible.
struct SanityHwSerialDetails { const char port[20]; uint32_t address; };
#define TMC_HW_DETAIL_ARGS(A) TERN(A##_HAS_HW_SERIAL, STRINGIFY(A##_HARDWARE_SERIAL), ""), TERN0(A##_HAS_HW_SERIAL, A##_SLAVE_ADDRESS)
#define TMC_HW_DETAIL(A) { TMC_HW_DETAIL_ARGS(A) }
constexpr SanityHwSerialDetails sanity_tmc_hw_details[] = {
TMC_HW_DETAIL(X), TMC_HW_DETAIL(X2),
TMC_HW_DETAIL(Y), TMC_HW_DETAIL(Y2),
TMC_HW_DETAIL(Z), TMC_HW_DETAIL(Z2), TMC_HW_DETAIL(Z3), TMC_HW_DETAIL(Z4),
TMC_HW_DETAIL(I), TMC_HW_DETAIL(J), TMC_HW_DETAIL(K),
TMC_HW_DETAIL(E0), TMC_HW_DETAIL(E1), TMC_HW_DETAIL(E2), TMC_HW_DETAIL(E3), TMC_HW_DETAIL(E4), TMC_HW_DETAIL(E5), TMC_HW_DETAIL(E6), TMC_HW_DETAIL(E7)
};
// constexpr compatible string comparison
constexpr bool str_eq_ce(const char * a, const char * b) {
return *a == *b && (*a == '\0' || str_eq_ce(a+1,b+1));
}
constexpr bool sc_hw_done(size_t start, size_t end) { return start == end; }
constexpr bool sc_hw_skip(const char *port_name) { return !(*port_name); }
constexpr bool sc_hw_match(const char *port_name, uint32_t address, size_t start, size_t end) {
return !sc_hw_done(start, end) && !sc_hw_skip(port_name) && (address == sanity_tmc_hw_details[start].address && str_eq_ce(port_name, sanity_tmc_hw_details[start].port));
}
constexpr int count_tmc_hw_serial_matches(const char *port_name, uint32_t address, size_t start, size_t end) {
return sc_hw_done(start, end) ? 0 : ((sc_hw_skip(port_name) ? 0 : (sc_hw_match(port_name, address, start, end) ? 1 : 0)) + count_tmc_hw_serial_matches(port_name, address, start + 1, end));
}
#define TMC_HWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_HARDWARE_SERIAL"
#define SA_NO_TMC_HW_C(A) static_assert(1 >= count_tmc_hw_serial_matches(TMC_HW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_hw_details)), TMC_HWSERIAL_CONFLICT_MSG(A));
SA_NO_TMC_HW_C(X); SA_NO_TMC_HW_C(X2);
SA_NO_TMC_HW_C(Y); SA_NO_TMC_HW_C(Y2);
SA_NO_TMC_HW_C(Z); SA_NO_TMC_HW_C(Z2); SA_NO_TMC_HW_C(Z3); SA_NO_TMC_HW_C(Z4);
SA_NO_TMC_HW_C(I); SA_NO_TMC_HW_C(J); SA_NO_TMC_HW_C(K);
SA_NO_TMC_HW_C(E0); SA_NO_TMC_HW_C(E1); SA_NO_TMC_HW_C(E2); SA_NO_TMC_HW_C(E3); SA_NO_TMC_HW_C(E4); SA_NO_TMC_HW_C(E5); SA_NO_TMC_HW_C(E6); SA_NO_TMC_HW_C(E7);
#endif
#if ANY_AXIS_HAS(SW_SERIAL)
struct SanitySwSerialDetails { int32_t txpin; int32_t rxpin; uint32_t address; };
#define TMC_SW_DETAIL_ARGS(A) TERN(A##_HAS_SW_SERIAL, A##_SERIAL_TX_PIN, -1), TERN(A##_HAS_SW_SERIAL, A##_SERIAL_RX_PIN, -1), TERN0(A##_HAS_SW_SERIAL, A##_SLAVE_ADDRESS)
#define TMC_SW_DETAIL(A) TMC_SW_DETAIL_ARGS(A)
constexpr SanitySwSerialDetails sanity_tmc_sw_details[] = {
TMC_SW_DETAIL(X), TMC_SW_DETAIL(X2),
TMC_SW_DETAIL(Y), TMC_SW_DETAIL(Y2),
TMC_SW_DETAIL(Z), TMC_SW_DETAIL(Z2), TMC_SW_DETAIL(Z3), TMC_SW_DETAIL(Z4),
TMC_SW_DETAIL(I), TMC_SW_DETAIL(J), TMC_SW_DETAIL(K),
TMC_SW_DETAIL(E0), TMC_SW_DETAIL(E1), TMC_SW_DETAIL(E2), TMC_SW_DETAIL(E3), TMC_SW_DETAIL(E4), TMC_SW_DETAIL(E5), TMC_SW_DETAIL(E6), TMC_SW_DETAIL(E7)
};
constexpr bool sc_sw_done(size_t start, size_t end) { return start == end; }
constexpr bool sc_sw_skip(int32_t txpin) { return txpin < 0; }
constexpr bool sc_sw_match(int32_t txpin, int32_t rxpin, uint32_t address, size_t start, size_t end) {
return !sc_sw_done(start, end) && !sc_sw_skip(txpin) && (txpin == sanity_tmc_sw_details[start].txpin || rxpin == sanity_tmc_sw_details[start].rxpin) && (address == sanity_tmc_sw_details[start].address);
}
constexpr int count_tmc_sw_serial_matches(int32_t txpin, int32_t rxpin, uint32_t address, size_t start, size_t end) {
return sc_sw_done(start, end) ? 0 : ((sc_sw_skip(txpin) ? 0 : (sc_sw_match(txpin, rxpin, address, start, end) ? 1 : 0)) + count_tmc_sw_serial_matches(txpin, rxpin, address, start + 1, end));
}
#define TMC_SWSERIAL_CONFLICT_MSG(A) STRINGIFY(A) "_SLAVE_ADDRESS conflicts with another driver using the same " STRINGIFY(A) "_SERIAL_RX_PIN or " STRINGIFY(A) "_SERIAL_TX_PIN"
#define SA_NO_TMC_SW_C(A) static_assert(1 >= count_tmc_sw_serial_matches(TMC_SW_DETAIL_ARGS(A), 0, COUNT(sanity_tmc_sw_details)), TMC_SWSERIAL_CONFLICT_MSG(A));
SA_NO_TMC_SW_C(X); SA_NO_TMC_SW_C(X2);
SA_NO_TMC_SW_C(Y); SA_NO_TMC_SW_C(Y2);
SA_NO_TMC_SW_C(Z); SA_NO_TMC_SW_C(Z2); SA_NO_TMC_SW_C(Z3); SA_NO_TMC_SW_C(Z4);
SA_NO_TMC_SW_C(I); SA_NO_TMC_SW_C(J); SA_NO_TMC_SW_C(K);
SA_NO_TMC_SW_C(E0); SA_NO_TMC_SW_C(E1); SA_NO_TMC_SW_C(E2); SA_NO_TMC_SW_C(E3); SA_NO_TMC_SW_C(E4); SA_NO_TMC_SW_C(E5); SA_NO_TMC_SW_C(E6); SA_NO_TMC_SW_C(E7);
#endif
#endif // HAS_TRINAMIC_CONFIG

205
Marlin/src/module/stepper/trinamic.h Executable file → Normal file
View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
@@ -46,6 +46,10 @@
#define TMC_Y_LABEL 'Y', '0'
#define TMC_Z_LABEL 'Z', '0'
#define TMC_I_LABEL 'I', '0'
#define TMC_J_LABEL 'J', '0'
#define TMC_K_LABEL 'K', '0'
#define TMC_X2_LABEL 'X', '2'
#define TMC_Y2_LABEL 'Y', '2'
#define TMC_Z2_LABEL 'Z', '2'
@@ -76,7 +80,27 @@ typedef struct {
uint8_t hstrt;
} chopper_timing_t;
static constexpr chopper_timing_t chopper_timing = CHOPPER_TIMING;
#ifndef CHOPPER_TIMING_X
#define CHOPPER_TIMING_X CHOPPER_TIMING
#endif
#if HAS_Y_AXIS && !defined(CHOPPER_TIMING_Y)
#define CHOPPER_TIMING_Y CHOPPER_TIMING
#endif
#if HAS_Z_AXIS && !defined(CHOPPER_TIMING_Z)
#define CHOPPER_TIMING_Z CHOPPER_TIMING
#endif
#if LINEAR_AXES >= 4 && !defined(CHOPPER_TIMING_I)
#define CHOPPER_TIMING_I CHOPPER_TIMING
#endif
#if LINEAR_AXES >= 5 && !defined(CHOPPER_TIMING_J)
#define CHOPPER_TIMING_J CHOPPER_TIMING
#endif
#if LINEAR_AXES >= 6 && !defined(CHOPPER_TIMING_K)
#define CHOPPER_TIMING_K CHOPPER_TIMING
#endif
#if HAS_EXTRUDERS && !defined(CHOPPER_TIMING_E)
#define CHOPPER_TIMING_E CHOPPER_TIMING
#endif
#if HAS_TMC220x
void tmc_serial_begin();
@@ -90,22 +114,24 @@ void reset_trinamic_drivers();
// X Stepper
#if AXIS_IS_TMC(X)
extern TMC_CLASS(X, X) stepperX;
static constexpr chopper_timing_t chopper_timing_X = CHOPPER_TIMING_X;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define X_ENABLE_INIT() NOOP
#define X_ENABLE_WRITE(STATE) stepperX.toff((STATE)==X_ENABLE_ON ? chopper_timing.toff : 0)
#define X_ENABLE_WRITE(STATE) stepperX.toff((STATE)==X_ENABLE_ON ? chopper_timing_X.toff : 0)
#define X_ENABLE_READ() stepperX.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(X)
#define X_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(X_STEP_PIN); }while(0)
#define X_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(X_STEP_PIN); }while(0)
#endif
#endif
// Y Stepper
#if AXIS_IS_TMC(Y)
extern TMC_CLASS(Y, Y) stepperY;
static constexpr chopper_timing_t chopper_timing_Y = CHOPPER_TIMING_Y;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define Y_ENABLE_INIT() NOOP
#define Y_ENABLE_WRITE(STATE) stepperY.toff((STATE)==Y_ENABLE_ON ? chopper_timing.toff : 0)
#define Y_ENABLE_WRITE(STATE) stepperY.toff((STATE)==Y_ENABLE_ON ? chopper_timing_Y.toff : 0)
#define Y_ENABLE_READ() stepperY.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(Y)
@@ -116,181 +142,276 @@ void reset_trinamic_drivers();
// Z Stepper
#if AXIS_IS_TMC(Z)
extern TMC_CLASS(Z, Z) stepperZ;
static constexpr chopper_timing_t chopper_timing_Z = CHOPPER_TIMING_Z;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define Z_ENABLE_INIT() NOOP
#define Z_ENABLE_WRITE(STATE) stepperZ.toff((STATE)==Z_ENABLE_ON ? chopper_timing.toff : 0)
#define Z_ENABLE_WRITE(STATE) stepperZ.toff((STATE)==Z_ENABLE_ON ? chopper_timing_Z.toff : 0)
#define Z_ENABLE_READ() stepperZ.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(Z)
#define Z_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(Z_STEP_PIN); }while(0)
#define Z_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(Z_STEP_PIN); }while(0)
#endif
#endif
// X2 Stepper
#if HAS_X2_ENABLE && AXIS_IS_TMC(X2)
extern TMC_CLASS(X2, X) stepperX2;
#ifndef CHOPPER_TIMING_X2
#define CHOPPER_TIMING_X2 CHOPPER_TIMING_X
#endif
static constexpr chopper_timing_t chopper_timing_X2 = CHOPPER_TIMING_X2;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define X2_ENABLE_INIT() NOOP
#define X2_ENABLE_WRITE(STATE) stepperX2.toff((STATE)==X_ENABLE_ON ? chopper_timing.toff : 0)
#define X2_ENABLE_WRITE(STATE) stepperX2.toff((STATE)==X_ENABLE_ON ? chopper_timing_X2.toff : 0)
#define X2_ENABLE_READ() stepperX2.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(X2)
#define X2_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(X2_STEP_PIN); }while(0)
#define X2_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(X2_STEP_PIN); }while(0)
#endif
#endif
// Y2 Stepper
#if HAS_Y2_ENABLE && AXIS_IS_TMC(Y2)
extern TMC_CLASS(Y2, Y) stepperY2;
#ifndef CHOPPER_TIMING_Y2
#define CHOPPER_TIMING_Y2 CHOPPER_TIMING_Y
#endif
static constexpr chopper_timing_t chopper_timing_Y2 = CHOPPER_TIMING_Y2;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define Y2_ENABLE_INIT() NOOP
#define Y2_ENABLE_WRITE(STATE) stepperY2.toff((STATE)==Y_ENABLE_ON ? chopper_timing.toff : 0)
#define Y2_ENABLE_WRITE(STATE) stepperY2.toff((STATE)==Y_ENABLE_ON ? chopper_timing_Y2.toff : 0)
#define Y2_ENABLE_READ() stepperY2.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(Y2)
#define Y2_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(Y2_STEP_PIN); }while(0)
#define Y2_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(Y2_STEP_PIN); }while(0)
#endif
#endif
// Z2 Stepper
#if HAS_Z2_ENABLE && AXIS_IS_TMC(Z2)
extern TMC_CLASS(Z2, Z) stepperZ2;
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(Z2)
#ifndef CHOPPER_TIMING_Z2
#define CHOPPER_TIMING_Z2 CHOPPER_TIMING_Z
#endif
static constexpr chopper_timing_t chopper_timing_Z2 = CHOPPER_TIMING_Z2;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define Z2_ENABLE_INIT() NOOP
#define Z2_ENABLE_WRITE(STATE) stepperZ2.toff((STATE)==Z_ENABLE_ON ? chopper_timing.toff : 0)
#define Z2_ENABLE_WRITE(STATE) stepperZ2.toff((STATE)==Z_ENABLE_ON ? chopper_timing_Z2.toff : 0)
#define Z2_ENABLE_READ() stepperZ2.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(Z2)
#define Z2_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(Z2_STEP_PIN); }while(0)
#define Z2_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(Z2_STEP_PIN); }while(0)
#endif
#endif
// Z3 Stepper
#if HAS_Z3_ENABLE && AXIS_IS_TMC(Z3)
extern TMC_CLASS(Z3, Z) stepperZ3;
#ifndef CHOPPER_TIMING_Z3
#define CHOPPER_TIMING_Z3 CHOPPER_TIMING_Z
#endif
static constexpr chopper_timing_t chopper_timing_Z3 = CHOPPER_TIMING_Z3;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define Z3_ENABLE_INIT() NOOP
#define Z3_ENABLE_WRITE(STATE) stepperZ3.toff((STATE)==Z_ENABLE_ON ? chopper_timing.toff : 0)
#define Z3_ENABLE_WRITE(STATE) stepperZ3.toff((STATE)==Z_ENABLE_ON ? chopper_timing_Z3.toff : 0)
#define Z3_ENABLE_READ() stepperZ3.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(Z3)
#define Z3_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(Z3_STEP_PIN); }while(0)
#define Z3_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(Z3_STEP_PIN); }while(0)
#endif
#endif
// Z4 Stepper
#if HAS_Z4_ENABLE && AXIS_IS_TMC(Z4)
extern TMC_CLASS(Z4, Z) stepperZ4;
#ifndef CHOPPER_TIMING_Z4
#define CHOPPER_TIMING_Z4 CHOPPER_TIMING_Z
#endif
static constexpr chopper_timing_t chopper_timing_Z4 = CHOPPER_TIMING_Z4;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define Z4_ENABLE_INIT() NOOP
#define Z4_ENABLE_WRITE(STATE) stepperZ4.toff((STATE)==Z_ENABLE_ON ? chopper_timing.toff : 0)
#define Z4_ENABLE_WRITE(STATE) stepperZ4.toff((STATE)==Z_ENABLE_ON ? chopper_timing_Z4.toff : 0)
#define Z4_ENABLE_READ() stepperZ4.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(Z4)
#define Z4_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(Z4_STEP_PIN); }while(0)
#define Z4_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(Z4_STEP_PIN); }while(0)
#endif
#endif
// I Stepper
#if AXIS_IS_TMC(I)
extern TMC_CLASS(I, I) stepperI;
static constexpr chopper_timing_t chopper_timing_I = CHOPPER_TIMING_I;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define I_ENABLE_INIT() NOOP
#define I_ENABLE_WRITE(STATE) stepperI.toff((STATE)==I_ENABLE_ON ? chopper_timing.toff : 0)
#define I_ENABLE_READ() stepperI.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(I)
#define I_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(I_STEP_PIN); }while(0)
#endif
#endif
// J Stepper
#if AXIS_IS_TMC(J)
extern TMC_CLASS(J, J) stepperJ;
static constexpr chopper_timing_t chopper_timing_J = CHOPPER_TIMING_J;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define J_ENABLE_INIT() NOOP
#define J_ENABLE_WRITE(STATE) stepperJ.toff((STATE)==J_ENABLE_ON ? chopper_timing.toff : 0)
#define J_ENABLE_READ() stepperJ.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(J)
#define J_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(J_STEP_PIN); }while(0)
#endif
#endif
// K Stepper
#if AXIS_IS_TMC(K)
extern TMC_CLASS(K, K) stepperK;
static constexpr chopper_timing_t chopper_timing_K = CHOPPER_TIMING_K;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define K_ENABLE_INIT() NOOP
#define K_ENABLE_WRITE(STATE) stepperK.toff((STATE)==K_ENABLE_ON ? chopper_timing.toff : 0)
#define K_ENABLE_READ() stepperK.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(K)
#define K_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(K_STEP_PIN); }while(0)
#endif
#endif
// E0 Stepper
#if AXIS_IS_TMC(E0)
extern TMC_CLASS_E(0) stepperE0;
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E0)
#ifndef CHOPPER_TIMING_E0
#define CHOPPER_TIMING_E0 CHOPPER_TIMING_E
#endif
static constexpr chopper_timing_t chopper_timing_E0 = CHOPPER_TIMING_E0;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define E0_ENABLE_INIT() NOOP
#define E0_ENABLE_WRITE(STATE) stepperE0.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
#define E0_ENABLE_WRITE(STATE) stepperE0.toff((STATE)==E_ENABLE_ON ? chopper_timing_E0.toff : 0)
#define E0_ENABLE_READ() stepperE0.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(E0)
#define E0_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E0_STEP_PIN); }while(0)
#define E0_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E0_STEP_PIN); }while(0)
#endif
#endif
// E1 Stepper
#if AXIS_IS_TMC(E1)
extern TMC_CLASS_E(1) stepperE1;
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E1)
#ifndef CHOPPER_TIMING_E1
#define CHOPPER_TIMING_E1 CHOPPER_TIMING_E
#endif
static constexpr chopper_timing_t chopper_timing_E1 = CHOPPER_TIMING_E1;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define E1_ENABLE_INIT() NOOP
#define E1_ENABLE_WRITE(STATE) stepperE1.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
#define E1_ENABLE_WRITE(STATE) stepperE1.toff((STATE)==E_ENABLE_ON ? chopper_timing_E1.toff : 0)
#define E1_ENABLE_READ() stepperE1.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(E1)
#define E1_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E1_STEP_PIN); }while(0)
#define E1_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E1_STEP_PIN); }while(0)
#endif
#endif
// E2 Stepper
#if AXIS_IS_TMC(E2)
extern TMC_CLASS_E(2) stepperE2;
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E2)
#ifndef CHOPPER_TIMING_E2
#define CHOPPER_TIMING_E2 CHOPPER_TIMING_E
#endif
static constexpr chopper_timing_t chopper_timing_E2 = CHOPPER_TIMING_E2;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define E2_ENABLE_INIT() NOOP
#define E2_ENABLE_WRITE(STATE) stepperE2.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
#define E2_ENABLE_WRITE(STATE) stepperE2.toff((STATE)==E_ENABLE_ON ? chopper_timing_E2.toff : 0)
#define E2_ENABLE_READ() stepperE2.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(E2)
#define E2_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E2_STEP_PIN); }while(0)
#define E2_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E2_STEP_PIN); }while(0)
#endif
#endif
// E3 Stepper
#if AXIS_IS_TMC(E3)
extern TMC_CLASS_E(3) stepperE3;
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E3)
#ifndef CHOPPER_TIMING_E3
#define CHOPPER_TIMING_E3 CHOPPER_TIMING_E
#endif
static constexpr chopper_timing_t chopper_timing_E3 = CHOPPER_TIMING_E3;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define E3_ENABLE_INIT() NOOP
#define E3_ENABLE_WRITE(STATE) stepperE3.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
#define E3_ENABLE_WRITE(STATE) stepperE3.toff((STATE)==E_ENABLE_ON ? chopper_timing_E3.toff : 0)
#define E3_ENABLE_READ() stepperE3.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(E3)
#define E3_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E3_STEP_PIN); }while(0)
#define E3_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E3_STEP_PIN); }while(0)
#endif
#endif
// E4 Stepper
#if AXIS_IS_TMC(E4)
extern TMC_CLASS_E(4) stepperE4;
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E4)
#ifndef CHOPPER_TIMING_E4
#define CHOPPER_TIMING_E4 CHOPPER_TIMING_E
#endif
static constexpr chopper_timing_t chopper_timing_E4 = CHOPPER_TIMING_E4;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define E4_ENABLE_INIT() NOOP
#define E4_ENABLE_WRITE(STATE) stepperE4.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
#define E4_ENABLE_WRITE(STATE) stepperE4.toff((STATE)==E_ENABLE_ON ? chopper_timing_E4.toff : 0)
#define E4_ENABLE_READ() stepperE4.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(E4)
#define E4_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E4_STEP_PIN); }while(0)
#define E4_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E4_STEP_PIN); }while(0)
#endif
#endif
// E5 Stepper
#if AXIS_IS_TMC(E5)
extern TMC_CLASS_E(5) stepperE5;
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E5)
#ifndef CHOPPER_TIMING_E5
#define CHOPPER_TIMING_E5 CHOPPER_TIMING_E
#endif
static constexpr chopper_timing_t chopper_timing_E5 = CHOPPER_TIMING_E5;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define E5_ENABLE_INIT() NOOP
#define E5_ENABLE_WRITE(STATE) stepperE5.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
#define E5_ENABLE_WRITE(STATE) stepperE5.toff((STATE)==E_ENABLE_ON ? chopper_timing_E5.toff : 0)
#define E5_ENABLE_READ() stepperE5.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(E5)
#define E5_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E5_STEP_PIN); }while(0)
#define E5_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E5_STEP_PIN); }while(0)
#endif
#endif
// E6 Stepper
#if AXIS_IS_TMC(E6)
extern TMC_CLASS_E(6) stepperE6;
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E6)
#ifndef CHOPPER_TIMING_E6
#define CHOPPER_TIMING_E6 CHOPPER_TIMING_E
#endif
static constexpr chopper_timing_t chopper_timing_E6 = CHOPPER_TIMING_E6;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define E6_ENABLE_INIT() NOOP
#define E6_ENABLE_WRITE(STATE) stepperE6.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
#define E6_ENABLE_WRITE(STATE) stepperE6.toff((STATE)==E_ENABLE_ON ? chopper_timing_E6.toff : 0)
#define E6_ENABLE_READ() stepperE6.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(E6)
#define E6_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E6_STEP_PIN); }while(0)
#define E6_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E6_STEP_PIN); }while(0)
#endif
#endif
// E7 Stepper
#if AXIS_IS_TMC(E7)
extern TMC_CLASS_E(7) stepperE7;
#if ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E7)
#ifndef CHOPPER_TIMING_E7
#define CHOPPER_TIMING_E7 CHOPPER_TIMING_E
#endif
static constexpr chopper_timing_t chopper_timing_E7 = CHOPPER_TIMING_E7;
#if ENABLED(SOFTWARE_DRIVER_ENABLE)
#define E7_ENABLE_INIT() NOOP
#define E7_ENABLE_WRITE(STATE) stepperE7.toff((STATE)==E_ENABLE_ON ? chopper_timing.toff : 0)
#define E7_ENABLE_WRITE(STATE) stepperE7.toff((STATE)==E_ENABLE_ON ? chopper_timing_E7.toff : 0)
#define E7_ENABLE_READ() stepperE7.isEnabled()
#endif
#if AXIS_HAS_SQUARE_WAVE(E7)
#define E7_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(E7_STEP_PIN); }while(0)
#define E7_STEP_WRITE(STATE) do{ if (STATE) TOGGLE(E7_STEP_PIN); }while(0)
#endif
#endif