From 759234af60c5770fe56ff35c9b3c3a45f2cd1ec7 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <sourcetree@thinkyhead.com>
Date: Sat, 27 Aug 2016 23:38:05 -0500
Subject: [PATCH] MINIMUM_STEPPER_PULSE option

---
 Marlin/Configuration_adv.h                    |  4 ++
 .../Cartesio/Configuration_adv.h              |  4 ++
 .../Felix/Configuration_adv.h                 |  4 ++
 .../Hephestos/Configuration_adv.h             |  4 ++
 .../Hephestos_2/Configuration_adv.h           |  4 ++
 .../K8200/Configuration_adv.h                 |  4 ++
 .../K8400/Configuration_adv.h                 |  4 ++
 .../RigidBot/Configuration_adv.h              |  4 ++
 .../SCARA/Configuration_adv.h                 |  4 ++
 .../TAZ4/Configuration_adv.h                  |  4 ++
 .../WITBOX/Configuration_adv.h                |  4 ++
 .../delta/biv2.5/Configuration_adv.h          |  4 ++
 .../delta/generic/Configuration_adv.h         |  4 ++
 .../delta/kossel_mini/Configuration_adv.h     |  4 ++
 .../delta/kossel_pro/Configuration_adv.h      |  4 ++
 .../delta/kossel_xl/Configuration_adv.h       |  4 ++
 .../makibox/Configuration_adv.h               |  4 ++
 .../tvrrug/Round2/Configuration_adv.h         |  4 ++
 Marlin/stepper.cpp                            | 40 ++++++++++++-------
 19 files changed, 97 insertions(+), 15 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 3a47c1312b..f6df89a850 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -533,6 +533,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/Cartesio/Configuration_adv.h b/Marlin/example_configurations/Cartesio/Configuration_adv.h
index dea8828755..0763b33823 100644
--- a/Marlin/example_configurations/Cartesio/Configuration_adv.h
+++ b/Marlin/example_configurations/Cartesio/Configuration_adv.h
@@ -533,6 +533,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/Felix/Configuration_adv.h b/Marlin/example_configurations/Felix/Configuration_adv.h
index dc58b55893..a24bca1a26 100644
--- a/Marlin/example_configurations/Felix/Configuration_adv.h
+++ b/Marlin/example_configurations/Felix/Configuration_adv.h
@@ -533,6 +533,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/Hephestos/Configuration_adv.h b/Marlin/example_configurations/Hephestos/Configuration_adv.h
index 9f252d4a2a..7b826b5277 100644
--- a/Marlin/example_configurations/Hephestos/Configuration_adv.h
+++ b/Marlin/example_configurations/Hephestos/Configuration_adv.h
@@ -533,6 +533,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/Hephestos_2/Configuration_adv.h b/Marlin/example_configurations/Hephestos_2/Configuration_adv.h
index 06ba9b2551..deb6262928 100644
--- a/Marlin/example_configurations/Hephestos_2/Configuration_adv.h
+++ b/Marlin/example_configurations/Hephestos_2/Configuration_adv.h
@@ -533,6 +533,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/K8200/Configuration_adv.h b/Marlin/example_configurations/K8200/Configuration_adv.h
index 4c870b17d6..d57fcea93d 100644
--- a/Marlin/example_configurations/K8200/Configuration_adv.h
+++ b/Marlin/example_configurations/K8200/Configuration_adv.h
@@ -539,6 +539,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 3
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/K8400/Configuration_adv.h b/Marlin/example_configurations/K8400/Configuration_adv.h
index 444f872344..7a84269818 100644
--- a/Marlin/example_configurations/K8400/Configuration_adv.h
+++ b/Marlin/example_configurations/K8400/Configuration_adv.h
@@ -533,6 +533,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/RigidBot/Configuration_adv.h b/Marlin/example_configurations/RigidBot/Configuration_adv.h
index 308b3ef0d2..faebf06ffa 100644
--- a/Marlin/example_configurations/RigidBot/Configuration_adv.h
+++ b/Marlin/example_configurations/RigidBot/Configuration_adv.h
@@ -533,6 +533,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/SCARA/Configuration_adv.h b/Marlin/example_configurations/SCARA/Configuration_adv.h
index 108c982244..a6d33e8aa8 100644
--- a/Marlin/example_configurations/SCARA/Configuration_adv.h
+++ b/Marlin/example_configurations/SCARA/Configuration_adv.h
@@ -533,6 +533,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/TAZ4/Configuration_adv.h b/Marlin/example_configurations/TAZ4/Configuration_adv.h
index 6014172912..6252c27964 100644
--- a/Marlin/example_configurations/TAZ4/Configuration_adv.h
+++ b/Marlin/example_configurations/TAZ4/Configuration_adv.h
@@ -541,6 +541,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/WITBOX/Configuration_adv.h b/Marlin/example_configurations/WITBOX/Configuration_adv.h
index 9f252d4a2a..7b826b5277 100644
--- a/Marlin/example_configurations/WITBOX/Configuration_adv.h
+++ b/Marlin/example_configurations/WITBOX/Configuration_adv.h
@@ -533,6 +533,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/delta/biv2.5/Configuration_adv.h b/Marlin/example_configurations/delta/biv2.5/Configuration_adv.h
index 62a8b14c99..bbafe89f6e 100644
--- a/Marlin/example_configurations/delta/biv2.5/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/biv2.5/Configuration_adv.h
@@ -535,6 +535,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/delta/generic/Configuration_adv.h b/Marlin/example_configurations/delta/generic/Configuration_adv.h
index 1981148abc..3345f32ec4 100644
--- a/Marlin/example_configurations/delta/generic/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/generic/Configuration_adv.h
@@ -535,6 +535,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
index 5dab25a92a..97a1712c8a 100644
--- a/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
@@ -534,6 +534,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h
index 30b3f4e8ee..2203ee7942 100644
--- a/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h
@@ -539,6 +539,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h
index e509fb3982..4532819852 100644
--- a/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h
@@ -535,6 +535,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/makibox/Configuration_adv.h b/Marlin/example_configurations/makibox/Configuration_adv.h
index 767adf6c05..addfc7acdf 100644
--- a/Marlin/example_configurations/makibox/Configuration_adv.h
+++ b/Marlin/example_configurations/makibox/Configuration_adv.h
@@ -533,6 +533,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h b/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
index e4c212fe95..1e8e626cc0 100644
--- a/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
+++ b/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
@@ -533,6 +533,10 @@
 // Moves (or segments) with fewer steps than this will be joined with the next move
 #define MIN_STEPS_PER_SEGMENT 6
 
+// The minimum pulse width (in µs) for stepping a stepper.
+// Set this if you find stepping unreliable, or if using a very fast CPU.
+#define MINIMUM_STEPPER_PULSE 0 // (µs) The smallest stepper pulse allowed
+
 // @section temperature
 
 // Control heater 0 and heater 1 in parallel.
diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp
index e27b03580f..64805f1acc 100644
--- a/Marlin/stepper.cpp
+++ b/Marlin/stepper.cpp
@@ -449,18 +449,30 @@ void Stepper::isr() {
       #define _APPLY_STEP(AXIS) AXIS ##_APPLY_STEP
       #define _INVERT_STEP_PIN(AXIS) INVERT_## AXIS ##_STEP_PIN
 
-      #define STEP_ADD(AXIS) \
+      #define PULSE_START(AXIS) \
         _COUNTER(AXIS) += current_block->steps[_AXIS(AXIS)]; \
         if (_COUNTER(AXIS) > 0) { _APPLY_STEP(AXIS)(!_INVERT_STEP_PIN(AXIS),0); }
 
+      #define PULSE_STOP(AXIS) \
+        if (_COUNTER(AXIS) > 0) { \
+          _COUNTER(AXIS) -= current_block->step_event_count; \
+          count_position[_AXIS(AXIS)] += count_direction[_AXIS(AXIS)]; \
+          _APPLY_STEP(AXIS)(_INVERT_STEP_PIN(AXIS),0); \
+        }
+
+      #if MINIMUM_STEPPER_PULSE > 0
+        static uint32_t pulse_start;
+        pulse_start = TCNT0;
+      #endif
+
       #if HAS_X_STEP
-        STEP_ADD(X);
+        PULSE_START(X);
       #endif
       #if HAS_Y_STEP
-        STEP_ADD(Y);
+        PULSE_START(Y);
       #endif
       #if HAS_Z_STEP
-        STEP_ADD(Z);
+        PULSE_START(Z);
       #endif
 
       #if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
@@ -475,25 +487,23 @@ void Stepper::isr() {
             if (counter_M[j] > 0) En_STEP_WRITE(j, !INVERT_E_STEP_PIN);
           }
         #else // !MIXING_EXTRUDER
-          STEP_ADD(E);
+          PULSE_START(E);
         #endif
       #endif // !ADVANCE && !LIN_ADVANCE
 
-      #define STEP_IF_COUNTER(AXIS) \
-        if (_COUNTER(AXIS) > 0) { \
-          _COUNTER(AXIS) -= current_block->step_event_count; \
-          count_position[_AXIS(AXIS)] += count_direction[_AXIS(AXIS)]; \
-          _APPLY_STEP(AXIS)(_INVERT_STEP_PIN(AXIS),0); \
-        }
+      #if MINIMUM_STEPPER_PULSE > 0
+        #define CYCLES_EATEN_BY_CODE 10
+        while ((uint32_t)(TCNT0 - pulse_start) < (MINIMUM_STEPPER_PULSE * (F_CPU / 1000000UL)) - CYCLES_EATEN_BY_CODE) { /* nada */ }
+      #endif
 
       #if HAS_X_STEP
-        STEP_IF_COUNTER(X);
+        PULSE_STOP(X);
       #endif
       #if HAS_Y_STEP
-        STEP_IF_COUNTER(Y);
+        PULSE_STOP(Y);
       #endif
       #if HAS_Z_STEP
-        STEP_IF_COUNTER(Z);
+        PULSE_STOP(Z);
       #endif
 
       #if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
@@ -510,7 +520,7 @@ void Stepper::isr() {
             }
           }
         #else // !MIXING_EXTRUDER
-          STEP_IF_COUNTER(E);
+          PULSE_STOP(E);
         #endif
       #endif // !ADVANCE && !LIN_ADVANCE