From c744516e072566fb48774976b66ce1f663bd385b Mon Sep 17 00:00:00 2001
From: vovodroid <vovodroid@users.noreply.github.com>
Date: Tue, 30 Apr 2024 13:16:15 +0300
Subject: [PATCH 1/7] Linear fan kickstart time

---
 Marlin/Configuration_adv.h           | 5 +++--
 Marlin/src/feature/controllerfan.cpp | 2 +-
 Marlin/src/module/planner.cpp        | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index f0066338c177..abfe12277778 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -602,8 +602,9 @@
  * gets it spinning reliably for a short time before setting the requested speed.
  * (Does not work on Sanguinololu with FAN_SOFT_PWM.)
  */
-//#define FAN_KICKSTART_TIME  100  // (ms)
-//#define FAN_KICKSTART_POWER 180  // 64-255
+//#define FAN_KICKSTART_TIME  100    // (ms)
+//#define FAN_KICKSTART_POWER 180    // 64-255
+//#define FAN_KICKSTART_LINEAR       // Set kickstart time linearly based on the speed, e.g. for 20% (51) it  will be FAN_KICKSTART_TIME * 0.2. Usefull for quick speed up to low speed.
 
 // Some coolers may require a non-zero "off" state.
 //#define FAN_OFF_PWM  1
diff --git a/Marlin/src/feature/controllerfan.cpp b/Marlin/src/feature/controllerfan.cpp
index acbae459e716..5fcda2376533 100644
--- a/Marlin/src/feature/controllerfan.cpp
+++ b/Marlin/src/feature/controllerfan.cpp
@@ -95,7 +95,7 @@ void ControllerFan::update() {
       static millis_t fan_kick_end = 0;
       if (speed > FAN_OFF_PWM) {
         if (!fan_kick_end) {
-          fan_kick_end = ms + FAN_KICKSTART_TIME; // May be longer based on slow update interval for controller fn check. Sets minimum
+          fan_kick_end = ms + FAN_KICKSTART_TIME TERN_(FAN_KICKSTART_LINEAR, * (speed / 255.0)); // May be longer based on slow update interval for controller fn check. Sets minimum
           speed = FAN_KICKSTART_POWER;
         }
         else if (PENDING(ms, fan_kick_end))
diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index c21230f662b3..109c24c7d13e 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -1312,7 +1312,7 @@ void Planner::recalculate(const_float_t safe_exit_speed_sqr) {
       static millis_t fan_kick_end[FAN_COUNT] = { 0 };
       if (fan_speed[f] > FAN_OFF_PWM) {
         if (fan_kick_end[f] == 0) {
-          fan_kick_end[f] = ms + FAN_KICKSTART_TIME;
+          fan_kick_end[f] = ms + FAN_KICKSTART_TIME TERN_(FAN_KICKSTART_LINEAR, * (fan_speed[f] / 255.0));
           fan_speed[f] = FAN_KICKSTART_POWER;
         }
         else if (PENDING(ms, fan_kick_end[f]))

From faa6ad2b5d087dabf4690ba770afec4867c9c978 Mon Sep 17 00:00:00 2001
From: vovodroid <vovodroid@users.noreply.github.com>
Date: Tue, 30 Apr 2024 13:16:15 +0300
Subject: [PATCH 2/7] Use delta between speed for time calculation, always
 apply full speed.

---
 Marlin/Configuration_adv.h    |  3 ++-
 Marlin/src/module/planner.cpp | 17 ++++++++++++-----
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index abfe12277778..8cea29b53cf5 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -604,7 +604,8 @@
  */
 //#define FAN_KICKSTART_TIME  100    // (ms)
 //#define FAN_KICKSTART_POWER 180    // 64-255
-//#define FAN_KICKSTART_LINEAR       // Set kickstart time linearly based on the speed, e.g. for 20% (51) it  will be FAN_KICKSTART_TIME * 0.2. Usefull for quick speed up to low speed.
+//#define FAN_KICKSTART_LINEAR       // Set kickstart time linearly based on the speed, e.g. for 20% (51) it  will be FAN_KICKSTART_TIME * 0.2.
+                                     // Usefull for quick speed up to low speed. Kickstart power will be set to 255.
 
 // Some coolers may require a non-zero "off" state.
 //#define FAN_OFF_PWM  1
diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index 109c24c7d13e..9d4e47ba5a51 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -1310,16 +1310,23 @@ void Planner::recalculate(const_float_t safe_exit_speed_sqr) {
 
     void Planner::kickstart_fan(uint8_t (&fan_speed)[FAN_COUNT], const millis_t &ms, const uint8_t f) {
       static millis_t fan_kick_end[FAN_COUNT] = { 0 };
+      static uint8_t  set_fan_speed[FAN_COUNT] = { 0 };
       if (fan_speed[f] > FAN_OFF_PWM) {
-        if (fan_kick_end[f] == 0) {
-          fan_kick_end[f] = ms + FAN_KICKSTART_TIME TERN_(FAN_KICKSTART_LINEAR, * (fan_speed[f] / 255.0));
-          fan_speed[f] = FAN_KICKSTART_POWER;
+        if (fan_kick_end[f] == 0 && fan_speed[f] > set_fan_speed[f]) {
+          fan_kick_end[f] = ms + FAN_KICKSTART_TIME TERN_(FAN_KICKSTART_LINEAR, * (fan_speed[f] - set_fan_speed[f]) / 255);
+          fan_speed[f] = TERN(FAN_KICKSTART_LINEAR, 255, FAN_KICKSTART_POWER);
         }
         else if (PENDING(ms, fan_kick_end[f]))
-          fan_speed[f] = FAN_KICKSTART_POWER;
+          fan_speed[f] = TERN(FAN_KICKSTART_LINEAR, 255, FAN_KICKSTART_POWER);
+             else {
+          fan_kick_end[f] = 0;
+          set_fan_speed[f] = fan_speed[f];
+             }
       }
-      else
+      else {
         fan_kick_end[f] = 0;
+        set_fan_speed[f] = fan_speed[f];
+      }
     }
 
   #endif

From 75a632b373762b7aec1b2bdf429eda96527f175c Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Fri, 17 May 2024 16:15:11 -0500
Subject: [PATCH 3/7] misc. cleanup

---
 Marlin/Configuration_adv.h         |  8 ++++----
 Marlin/src/inc/Conditionals_post.h |  2 +-
 Marlin/src/inc/SanityCheck.h       |  8 ++++++--
 Marlin/src/module/planner.cpp      | 19 ++++++++-----------
 4 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 8cea29b53cf5..c69f59778710 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -602,10 +602,10 @@
  * gets it spinning reliably for a short time before setting the requested speed.
  * (Does not work on Sanguinololu with FAN_SOFT_PWM.)
  */
-//#define FAN_KICKSTART_TIME  100    // (ms)
-//#define FAN_KICKSTART_POWER 180    // 64-255
-//#define FAN_KICKSTART_LINEAR       // Set kickstart time linearly based on the speed, e.g. for 20% (51) it  will be FAN_KICKSTART_TIME * 0.2.
-                                     // Usefull for quick speed up to low speed. Kickstart power will be set to 255.
+//#define FAN_KICKSTART_TIME  100  // (ms)
+//#define FAN_KICKSTART_POWER 180  // 64-255
+//#define FAN_KICKSTART_LINEAR     // Set kickstart time linearly based on the speed, e.g. for 20% (51) it will be FAN_KICKSTART_TIME * 0.2.
+                                   // Useful for quick speed up to low speed. Kickstart power must be set to 255.
 
 // Some coolers may require a non-zero "off" state.
 //#define FAN_OFF_PWM  1
diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h
index 64c95fa6c413..678a03445819 100644
--- a/Marlin/src/inc/Conditionals_post.h
+++ b/Marlin/src/inc/Conditionals_post.h
@@ -2752,7 +2752,7 @@
 
 // Fan Kickstart
 #if FAN_KICKSTART_TIME && !defined(FAN_KICKSTART_POWER)
-  #define FAN_KICKSTART_POWER 180
+  #define FAN_KICKSTART_POWER TERN(FAN_KICKSTART_LINEAR, 255, 180)
 #endif
 
 // Servos
diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h
index 5f14c568ae24..c99e704a5431 100644
--- a/Marlin/src/inc/SanityCheck.h
+++ b/Marlin/src/inc/SanityCheck.h
@@ -1011,8 +1011,12 @@ static_assert(NUM_SERVOS <= NUM_SERVO_PLUGS, "NUM_SERVOS (or some servo index) i
 #endif
 
 // Fan Kickstart power
-#if FAN_KICKSTART_TIME && !WITHIN(FAN_KICKSTART_POWER, 64, 255)
-  #error "FAN_KICKSTART_POWER must be an integer from 64 to 255."
+#if FAN_KICKSTART_TIME
+  #if ENABLED(FAN_KICKSTART_LINEAR) && FAN_KICKSTART_POWER != 255
+    #error "FAN_KICKSTART_LINEAR requires a FAN_KICKSTART_POWER of 255."
+  #elif !WITHIN(FAN_KICKSTART_POWER, 64, 255)
+    #error "FAN_KICKSTART_POWER must be an integer from 64 to 255."
+  #endif
 #endif
 
 /**
diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index 9d4e47ba5a51..c7d927afb661 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -1314,19 +1314,16 @@ void Planner::recalculate(const_float_t safe_exit_speed_sqr) {
       if (fan_speed[f] > FAN_OFF_PWM) {
         if (fan_kick_end[f] == 0 && fan_speed[f] > set_fan_speed[f]) {
           fan_kick_end[f] = ms + FAN_KICKSTART_TIME TERN_(FAN_KICKSTART_LINEAR, * (fan_speed[f] - set_fan_speed[f]) / 255);
-          fan_speed[f] = TERN(FAN_KICKSTART_LINEAR, 255, FAN_KICKSTART_POWER);
+          fan_speed[f] = FAN_KICKSTART_POWER;
+          return;
+        }
+        else if (PENDING(ms, fan_kick_end[f])) {
+          fan_speed[f] = FAN_KICKSTART_POWER;
+          return;
         }
-        else if (PENDING(ms, fan_kick_end[f]))
-          fan_speed[f] = TERN(FAN_KICKSTART_LINEAR, 255, FAN_KICKSTART_POWER);
-             else {
-          fan_kick_end[f] = 0;
-          set_fan_speed[f] = fan_speed[f];
-             }
-      }
-      else {
-        fan_kick_end[f] = 0;
-        set_fan_speed[f] = fan_speed[f];
       }
+      fan_kick_end[f] = 0;
+      set_fan_speed[f] = fan_speed[f];
     }
 
   #endif

From 5eaccb482057acf84c422f462c47f7f3b0fe041c Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Fri, 17 May 2024 16:26:57 -0500
Subject: [PATCH 4/7] optional semi-kick

---
 Marlin/src/feature/controllerfan.cpp |  2 +-
 Marlin/src/module/planner.cpp        | 16 ++++++++--------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/Marlin/src/feature/controllerfan.cpp b/Marlin/src/feature/controllerfan.cpp
index 5fcda2376533..d6e13a6ff1f7 100644
--- a/Marlin/src/feature/controllerfan.cpp
+++ b/Marlin/src/feature/controllerfan.cpp
@@ -95,7 +95,7 @@ void ControllerFan::update() {
       static millis_t fan_kick_end = 0;
       if (speed > FAN_OFF_PWM) {
         if (!fan_kick_end) {
-          fan_kick_end = ms + FAN_KICKSTART_TIME TERN_(FAN_KICKSTART_LINEAR, * (speed / 255.0)); // May be longer based on slow update interval for controller fn check. Sets minimum
+          fan_kick_end = ms + (FAN_KICKSTART_TIME) TERN_(FAN_KICKSTART_LINEAR, * speed / 255); // May be longer based on slow update interval for controller fn check. Sets minimum
           speed = FAN_KICKSTART_POWER;
         }
         else if (PENDING(ms, fan_kick_end))
diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index c7d927afb661..f9c902b39786 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -1310,20 +1310,20 @@ void Planner::recalculate(const_float_t safe_exit_speed_sqr) {
 
     void Planner::kickstart_fan(uint8_t (&fan_speed)[FAN_COUNT], const millis_t &ms, const uint8_t f) {
       static millis_t fan_kick_end[FAN_COUNT] = { 0 };
-      static uint8_t  set_fan_speed[FAN_COUNT] = { 0 };
+      #if ENABLED(FAN_KICKSTART_LINEAR)
+        static uint8_t  set_fan_speed[FAN_COUNT] = { 0 };
+      #endif
       if (fan_speed[f] > FAN_OFF_PWM) {
-        if (fan_kick_end[f] == 0 && fan_speed[f] > set_fan_speed[f]) {
-          fan_kick_end[f] = ms + FAN_KICKSTART_TIME TERN_(FAN_KICKSTART_LINEAR, * (fan_speed[f] - set_fan_speed[f]) / 255);
-          fan_speed[f] = FAN_KICKSTART_POWER;
-          return;
-        }
-        else if (PENDING(ms, fan_kick_end[f])) {
+        const bool first_kick = fan_kick_end[f] == 0 && TERN1(FAN_KICKSTART_LINEAR, fan_speed[f] > set_fan_speed[f]);
+        if (first_kick)
+          fan_kick_end[f] = ms + (FAN_KICKSTART_TIME) TERN_(FAN_KICKSTART_LINEAR, * (fan_speed[f] - set_fan_speed[f]) / 255);
+        if (first_kick || PENDING(ms, fan_kick_end[f])) {
           fan_speed[f] = FAN_KICKSTART_POWER;
           return;
         }
       }
       fan_kick_end[f] = 0;
-      set_fan_speed[f] = fan_speed[f];
+      TERN_(FAN_KICKSTART_LINEAR, set_fan_speed[f] = fan_speed[f]);
     }
 
   #endif

From a36201f5a0b86b11669b2e4c129c52fbf8af330f Mon Sep 17 00:00:00 2001
From: vovodroid <vovodroid@users.noreply.github.com>
Date: Sat, 18 May 2024 21:54:44 +0300
Subject: [PATCH 5/7] Revert controller fan

---
 Marlin/src/feature/controllerfan.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Marlin/src/feature/controllerfan.cpp b/Marlin/src/feature/controllerfan.cpp
index d6e13a6ff1f7..acbae459e716 100644
--- a/Marlin/src/feature/controllerfan.cpp
+++ b/Marlin/src/feature/controllerfan.cpp
@@ -95,7 +95,7 @@ void ControllerFan::update() {
       static millis_t fan_kick_end = 0;
       if (speed > FAN_OFF_PWM) {
         if (!fan_kick_end) {
-          fan_kick_end = ms + (FAN_KICKSTART_TIME) TERN_(FAN_KICKSTART_LINEAR, * speed / 255); // May be longer based on slow update interval for controller fn check. Sets minimum
+          fan_kick_end = ms + FAN_KICKSTART_TIME; // May be longer based on slow update interval for controller fn check. Sets minimum
           speed = FAN_KICKSTART_POWER;
         }
         else if (PENDING(ms, fan_kick_end))

From c6b98e55e6016cb56e217de64121c9311af32739 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Thu, 4 Jul 2024 21:16:02 -0500
Subject: [PATCH 6/7] comma

---
 Marlin/Configuration_adv.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index c69f59778710..7606c140d4ea 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -604,7 +604,7 @@
  */
 //#define FAN_KICKSTART_TIME  100  // (ms)
 //#define FAN_KICKSTART_POWER 180  // 64-255
-//#define FAN_KICKSTART_LINEAR     // Set kickstart time linearly based on the speed, e.g. for 20% (51) it will be FAN_KICKSTART_TIME * 0.2.
+//#define FAN_KICKSTART_LINEAR     // Set kickstart time linearly based on the speed, e.g., for 20% (51) it will be FAN_KICKSTART_TIME * 0.2.
                                    // Useful for quick speed up to low speed. Kickstart power must be set to 255.
 
 // Some coolers may require a non-zero "off" state.

From 7187a9e6e6dfb5c640baf75c65899834ed5849c6 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Thu, 4 Jul 2024 21:17:04 -0500
Subject: [PATCH 7/7] ws

---
 Marlin/src/module/planner.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index f9c902b39786..1624768d38ca 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -1311,7 +1311,7 @@ void Planner::recalculate(const_float_t safe_exit_speed_sqr) {
     void Planner::kickstart_fan(uint8_t (&fan_speed)[FAN_COUNT], const millis_t &ms, const uint8_t f) {
       static millis_t fan_kick_end[FAN_COUNT] = { 0 };
       #if ENABLED(FAN_KICKSTART_LINEAR)
-        static uint8_t  set_fan_speed[FAN_COUNT] = { 0 };
+        static uint8_t set_fan_speed[FAN_COUNT] = { 0 };
       #endif
       if (fan_speed[f] > FAN_OFF_PWM) {
         const bool first_kick = fan_kick_end[f] == 0 && TERN1(FAN_KICKSTART_LINEAR, fan_speed[f] > set_fan_speed[f]);