From cf02107e6a8f9a122f15b38ed6b699215ee7cf16 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Wed, 25 Jan 2023 21:37:10 -0600
Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20Refine=20Input=20Shaping=20check?=
 =?UTF-8?q?=20(#25280)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Marlin/src/inc/SanityCheck.h  | 15 +++++++++++----
 Marlin/src/inc/Warnings.cpp   |  7 +++++++
 Marlin/src/module/stepper.cpp |  8 ++++----
 Marlin/src/module/stepper.h   | 27 ++++++++++++++-------------
 4 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h
index 1aadbb19e3e..d571ddd7f4a 100644
--- a/Marlin/src/inc/SanityCheck.h
+++ b/Marlin/src/inc/SanityCheck.h
@@ -4379,10 +4379,17 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
     #error "Input Shaping is not compatible with POLARGRAPH kinematics."
   #elif ENABLED(DIRECT_STEPPING)
     #error "Input Shaping is not compatible with DIRECT_STEPPING."
-  #elif ENABLED(INPUT_SHAPING_X) && ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX)
-    #error "INPUT_SHAPING_X is not supported with COREXY, COREYX, COREXZ, COREZX, or MARKFORGED_*."
-  #elif ENABLED(INPUT_SHAPING_Y) && ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX)
-    #error "INPUT_SHAPING_Y is not supported with COREXY, COREYX, COREYZ, COREZY, or MARKFORGED_*."
+  #elif BOTH(INPUT_SHAPING_X, CORE_IS_XZ)
+    #error "INPUT_SHAPING_X is not supported with COREXZ."
+  #elif BOTH(INPUT_SHAPING_Y, CORE_IS_YZ)
+    #error "INPUT_SHAPING_Y is not supported with COREYZ."
+  #elif ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
+    #if !BOTH(INPUT_SHAPING_X, INPUT_SHAPING_Y)
+      #error "INPUT_SHAPING_X and INPUT_SHAPING_Y must both be enabled for COREXY, COREYX, or MARKFORGED_*."
+    #else
+      static_assert(SHAPING_FREQ_X == SHAPING_FREQ_Y, "SHAPING_FREQ_X and SHAPING_FREQ_Y must be the same for COREXY / COREYX / MARKFORGED_*.");
+      static_assert(SHAPING_ZETA_X == SHAPING_ZETA_Y, "SHAPING_ZETA_X and SHAPING_ZETA_Y must be the same for COREXY / COREYX / MARKFORGED_*.");
+    #endif
   #endif
 
   #ifdef __AVR__
diff --git a/Marlin/src/inc/Warnings.cpp b/Marlin/src/inc/Warnings.cpp
index 561c8f43a34..1d1426936f9 100644
--- a/Marlin/src/inc/Warnings.cpp
+++ b/Marlin/src/inc/Warnings.cpp
@@ -790,3 +790,10 @@
 #if BOTH(POLAR, S_CURVE_ACCELERATION)
   #warning "POLAR kinematics may not work well with S_CURVE_ACCELERATION."
 #endif
+
+/**
+ * Input Shaping
+ */
+#if HAS_SHAPING && ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
+  #warning "Input Shaping for CORE / MARKFORGED kinematic axes is still experimental."
+#endif
diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp
index 2a9487f0969..54b52cd16e0 100644
--- a/Marlin/src/module/stepper.cpp
+++ b/Marlin/src/module/stepper.cpp
@@ -3020,7 +3020,7 @@ void Stepper::init() {
    * Calculate a fixed point factor to apply to the signal and its echo
    * when shaping an axis.
    */
-  void Stepper::set_shaping_damping_ratio(const AxisEnum axis, const float zeta) {
+  void Stepper::set_shaping_damping_ratio(const AxisEnum axis, const_float_t zeta) {
     // from the damping ratio, get a factor that can be applied to advance_dividend for fixed point maths
     // for ZV, we use amplitudes 1/(1+K) and K/(1+K) where K = exp(-zeta * M_PI / sqrt(1.0f - zeta * zeta))
     // which can be converted to 1:7 fixed point with an excellent fit with a 3rd order polynomial
@@ -3029,9 +3029,9 @@ void Stepper::init() {
     else if (zeta >= 1.0f) factor2 = 0.0f;
     else {
       factor2 = 64.44056192 + -99.02008832 * zeta;
-      const float zeta2 = zeta * zeta;
+      const_float_t zeta2 = zeta * zeta;
       factor2 += -7.58095488 * zeta2;
-      const float zeta3 = zeta2 * zeta;
+      const_float_t zeta3 = zeta2 * zeta;
       factor2 += 43.073216 * zeta3;
       factor2 = floor(factor2);
     }
@@ -3049,7 +3049,7 @@ void Stepper::init() {
     return -1;
   }
 
-  void Stepper::set_shaping_frequency(const AxisEnum axis, const float freq) {
+  void Stepper::set_shaping_frequency(const AxisEnum axis, const_float_t freq) {
     // enabling or disabling shaping whilst moving can result in lost steps
     planner.synchronize();
 
diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h
index e86498e841d..3bbfeac9cab 100644
--- a/Marlin/src/module/stepper.h
+++ b/Marlin/src/module/stepper.h
@@ -154,38 +154,39 @@
 
 // Add time for each stepper
 #if HAS_X_STEP
-  #define ISR_X_STEPPER_CYCLES  ISR_STEPPER_CYCLES
+  #define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES
 #endif
 #if HAS_Y_STEP
-  #define ISR_Y_STEPPER_CYCLES  ISR_STEPPER_CYCLES
+  #define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES
 #endif
 #if HAS_Z_STEP
-  #define ISR_Z_STEPPER_CYCLES  ISR_STEPPER_CYCLES
+  #define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES
 #endif
 #if HAS_I_STEP
-  #define ISR_I_STEPPER_CYCLES  ISR_STEPPER_CYCLES
+  #define ISR_I_STEPPER_CYCLES ISR_STEPPER_CYCLES
 #endif
 #if HAS_J_STEP
-  #define ISR_J_STEPPER_CYCLES  ISR_STEPPER_CYCLES
+  #define ISR_J_STEPPER_CYCLES ISR_STEPPER_CYCLES
 #endif
 #if HAS_K_STEP
-  #define ISR_K_STEPPER_CYCLES  ISR_STEPPER_CYCLES
+  #define ISR_K_STEPPER_CYCLES ISR_STEPPER_CYCLES
 #endif
 #if HAS_U_STEP
-  #define ISR_U_STEPPER_CYCLES  ISR_STEPPER_CYCLES
+  #define ISR_U_STEPPER_CYCLES ISR_STEPPER_CYCLES
 #endif
 #if HAS_V_STEP
-  #define ISR_V_STEPPER_CYCLES  ISR_STEPPER_CYCLES
+  #define ISR_V_STEPPER_CYCLES ISR_STEPPER_CYCLES
 #endif
 #if HAS_W_STEP
-  #define ISR_W_STEPPER_CYCLES  ISR_STEPPER_CYCLES
+  #define ISR_W_STEPPER_CYCLES ISR_STEPPER_CYCLES
 #endif
 #if HAS_EXTRUDERS
-  #define ISR_E_STEPPER_CYCLES  ISR_STEPPER_CYCLES    // E is always interpolated, even for mixing extruders
+  #define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES // E is always interpolated, even for mixing extruders
 #endif
 
 // And the total minimum loop time, not including the base
-#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_GANG(+ ISR_E_STEPPER_CYCLES, + ISR_X_STEPPER_CYCLES, + ISR_Y_STEPPER_CYCLES, + ISR_Z_STEPPER_CYCLES, + ISR_I_STEPPER_CYCLES, + ISR_J_STEPPER_CYCLES, + ISR_K_STEPPER_CYCLES, + ISR_U_STEPPER_CYCLES, + ISR_V_STEPPER_CYCLES, + ISR_W_STEPPER_CYCLES))
+#define _PLUS_AXIS_CYCLES(A) + (ISR_##A##_STEPPER_CYCLES)
+#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_MAP(_PLUS_AXIS_CYCLES))
 
 // Calculate the minimum MPU cycles needed per pulse to enforce, limited to the max stepper rate
 #define _MIN_STEPPER_PULSE_CYCLES(N) _MAX(uint32_t((F_CPU) / (MAXIMUM_STEPPER_RATE)), ((F_CPU) / 500000UL) * (N))
@@ -802,9 +803,9 @@ class Stepper {
     }
 
     #if HAS_SHAPING
-      static void set_shaping_damping_ratio(const AxisEnum axis, const float zeta);
+      static void set_shaping_damping_ratio(const AxisEnum axis, const_float_t zeta);
       static float get_shaping_damping_ratio(const AxisEnum axis);
-      static void set_shaping_frequency(const AxisEnum axis, const float freq);
+      static void set_shaping_frequency(const AxisEnum axis, const_float_t freq);
       static float get_shaping_frequency(const AxisEnum axis);
     #endif