@@ -194,6 +194,10 @@ uint32_t Stepper::acceleration_time, Stepper::deceleration_time;
194
194
uint8_t Stepper::steps_per_isr = 1 ; // Count of steps to perform per Stepper ISR call
195
195
#endif
196
196
197
+ #if DISABLED(OLD_ADAPTIVE_MULTISTEPPING)
198
+ hal_timer_t Stepper::time_spent_in_isr = 0 , Stepper::time_spent_out_isr = 0 ;
199
+ #endif
200
+
197
201
#if ENABLED(FREEZE_FEATURE)
198
202
bool Stepper::frozen; // = false
199
203
#endif
@@ -614,27 +618,26 @@ void Stepper::set_directions() {
614
618
TERN_ (HAS_V_DIR, SET_STEP_DIR (V));
615
619
TERN_ (HAS_W_DIR, SET_STEP_DIR (W));
616
620
617
- #if ENABLED(MIXING_EXTRUDER)
621
+ #if HAS_EXTRUDERS
618
622
// Because this is valid for the whole block we don't know
619
623
// what E steppers will step. Likely all. Set all.
620
624
if (motor_direction (E_AXIS)) {
621
- MIXER_STEPPER_LOOP (j) REV_E_DIR (j);
622
- count_direction.e = -1 ;
623
- }
624
- else {
625
- MIXER_STEPPER_LOOP (j) NORM_E_DIR (j);
626
- count_direction.e = 1 ;
627
- }
628
- #elif HAS_EXTRUDERS
629
- if (motor_direction (E_AXIS)) {
630
- REV_E_DIR (stepper_extruder);
625
+ #if ENABLED(MIXING_EXTRUDER)
626
+ MIXER_STEPPER_LOOP (j) REV_E_DIR (j);
627
+ #else
628
+ REV_E_DIR (stepper_extruder);
629
+ #endif
631
630
count_direction.e = -1 ;
632
631
}
633
632
else {
634
- NORM_E_DIR (stepper_extruder);
633
+ #if ENABLED(MIXING_EXTRUDER)
634
+ MIXER_STEPPER_LOOP (j) NORM_E_DIR (j);
635
+ #else
636
+ NORM_E_DIR (stepper_extruder);
637
+ #endif
635
638
count_direction.e = 1 ;
636
639
}
637
- #endif
640
+ #endif // HAS_EXTRUDERS
638
641
639
642
DIR_WAIT_AFTER ();
640
643
}
@@ -1587,16 +1590,44 @@ void Stepper::isr() {
1587
1590
*/
1588
1591
min_ticks = HAL_timer_get_count (MF_TIMER_STEP) + hal_timer_t (TERN (__AVR__, 8 , 1 ) * (STEPPER_TIMER_TICKS_PER_US));
1589
1592
1590
- /* *
1591
- * NB: If for some reason the stepper monopolizes the MPU, eventually the
1592
- * timer will wrap around (and so will 'next_isr_ticks'). So, limit the
1593
- * loop to 10 iterations. Beyond that, there's no way to ensure correct pulse
1594
- * timing, since the MCU isn't fast enough.
1595
- */
1596
- if (!--max_loops) next_isr_ticks = min_ticks;
1593
+ #if ENABLED(OLD_ADAPTIVE_MULTISTEPPING)
1594
+ /* *
1595
+ * NB: If for some reason the stepper monopolizes the MPU, eventually the
1596
+ * timer will wrap around (and so will 'next_isr_ticks'). So, limit the
1597
+ * loop to 10 iterations. Beyond that, there's no way to ensure correct pulse
1598
+ * timing, since the MCU isn't fast enough.
1599
+ */
1600
+ if (!--max_loops) next_isr_ticks = min_ticks;
1601
+ #endif
1597
1602
1598
1603
// Advance pulses if not enough time to wait for the next ISR
1599
- } while (next_isr_ticks < min_ticks);
1604
+ } while (TERN (OLD_ADAPTIVE_MULTISTEPPING, true , --max_loops) && next_isr_ticks < min_ticks);
1605
+
1606
+ #if DISABLED(OLD_ADAPTIVE_MULTISTEPPING)
1607
+
1608
+ // Track the time spent in the ISR
1609
+ const hal_timer_t time_spent = HAL_timer_get_count (MF_TIMER_STEP);
1610
+ time_spent_in_isr += time_spent;
1611
+
1612
+ if (next_isr_ticks < min_ticks) {
1613
+ next_isr_ticks = min_ticks;
1614
+
1615
+ // When forced out of the ISR, increase multi-stepping
1616
+ #if MULTISTEPPING_LIMIT > 1
1617
+ if (steps_per_isr < MULTISTEPPING_LIMIT) {
1618
+ steps_per_isr <<= 1 ;
1619
+ // ticks_nominal will need to be recalculated if we are in cruise phase
1620
+ ticks_nominal = 0 ;
1621
+ }
1622
+ #endif
1623
+ }
1624
+ else {
1625
+ // Track the time spent voluntarily outside the ISR
1626
+ time_spent_out_isr += next_isr_ticks;
1627
+ time_spent_out_isr -= time_spent;
1628
+ }
1629
+
1630
+ #endif // !OLD_ADAPTIVE_MULTISTEPPING
1600
1631
1601
1632
// Now 'next_isr_ticks' contains the period to the next Stepper ISR - And we are
1602
1633
// sure that the time has not arrived yet - Warrantied by the scheduler
@@ -2091,44 +2122,56 @@ hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) {
2091
2122
2092
2123
// Get the timer interval and the number of loops to perform per tick
2093
2124
hal_timer_t Stepper::calc_multistep_timer_interval (uint32_t step_rate) {
2094
- #if MULTISTEPPING_LIMIT == 1
2095
2125
2096
- // Just make sure the step rate is doable
2097
- NOMORE (step_rate, uint32_t (MAX_STEP_ISR_FREQUENCY_1X));
2126
+ #if ENABLED(OLD_ADAPTIVE_MULTISTEPPING)
2098
2127
2099
- # else
2128
+ # if MULTISTEPPING_LIMIT == 1
2100
2129
2101
- // The stepping frequency limits for each multistepping rate
2102
- static const uint32_t limit[] PROGMEM = {
2103
- ( MAX_STEP_ISR_FREQUENCY_1X )
2104
- , ( MAX_STEP_ISR_FREQUENCY_2X >> 1 )
2105
- #if MULTISTEPPING_LIMIT >= 4
2106
- , ( MAX_STEP_ISR_FREQUENCY_4X >> 2 )
2107
- #endif
2108
- #if MULTISTEPPING_LIMIT >= 8
2109
- , ( MAX_STEP_ISR_FREQUENCY_8X >> 3 )
2110
- #endif
2111
- #if MULTISTEPPING_LIMIT >= 16
2112
- , ( MAX_STEP_ISR_FREQUENCY_16X >> 4 )
2113
- #endif
2114
- #if MULTISTEPPING_LIMIT >= 32
2115
- , ( MAX_STEP_ISR_FREQUENCY_32X >> 5 )
2116
- #endif
2117
- #if MULTISTEPPING_LIMIT >= 64
2118
- , ( MAX_STEP_ISR_FREQUENCY_64X >> 6 )
2119
- #endif
2120
- #if MULTISTEPPING_LIMIT >= 128
2121
- , (MAX_STEP_ISR_FREQUENCY_128X >> 7 )
2122
- #endif
2123
- };
2130
+ // Just make sure the step rate is doable
2131
+ NOMORE (step_rate, uint32_t (MAX_STEP_ISR_FREQUENCY_1X));
2124
2132
2125
- // Find a doable step rate using multistepping
2126
- uint8_t multistep = 1 ;
2127
- for (uint8_t i = 0 ; i < COUNT (limit) && step_rate > uint32_t (pgm_read_dword (&limit[i])); ++i) {
2128
- step_rate >>= 1 ;
2129
- multistep <<= 1 ;
2130
- }
2131
- steps_per_isr = multistep;
2133
+ #else
2134
+
2135
+ // The stepping frequency limits for each multistepping rate
2136
+ static const uint32_t limit[] PROGMEM = {
2137
+ ( MAX_STEP_ISR_FREQUENCY_1X )
2138
+ , (((F_CPU) / ISR_EXECUTION_CYCLES (1 )) >> 1 )
2139
+ #if MULTISTEPPING_LIMIT >= 4
2140
+ , (((F_CPU) / ISR_EXECUTION_CYCLES (2 )) >> 2 )
2141
+ #endif
2142
+ #if MULTISTEPPING_LIMIT >= 8
2143
+ , (((F_CPU) / ISR_EXECUTION_CYCLES (3 )) >> 3 )
2144
+ #endif
2145
+ #if MULTISTEPPING_LIMIT >= 16
2146
+ , (((F_CPU) / ISR_EXECUTION_CYCLES (4 )) >> 4 )
2147
+ #endif
2148
+ #if MULTISTEPPING_LIMIT >= 32
2149
+ , (((F_CPU) / ISR_EXECUTION_CYCLES (5 )) >> 5 )
2150
+ #endif
2151
+ #if MULTISTEPPING_LIMIT >= 64
2152
+ , (((F_CPU) / ISR_EXECUTION_CYCLES (6 )) >> 6 )
2153
+ #endif
2154
+ #if MULTISTEPPING_LIMIT >= 128
2155
+ , (((F_CPU) / ISR_EXECUTION_CYCLES (7 )) >> 7 )
2156
+ #endif
2157
+ };
2158
+
2159
+ // Find a doable step rate using multistepping
2160
+ uint8_t multistep = 1 ;
2161
+ for (uint8_t i = 0 ; i < COUNT (limit) && step_rate > uint32_t (pgm_read_dword (&limit[i])); ++i) {
2162
+ step_rate >>= 1 ;
2163
+ multistep <<= 1 ;
2164
+ }
2165
+ steps_per_isr = multistep;
2166
+
2167
+ #endif
2168
+
2169
+ #elif MULTISTEPPING_LIMIT > 1
2170
+
2171
+ uint8_t loops = steps_per_isr;
2172
+ if (MULTISTEPPING_LIMIT >= 16 && loops >= 16 ) { step_rate >>= 4 ; loops >>= 4 ; }
2173
+ if (MULTISTEPPING_LIMIT >= 4 && loops >= 4 ) { step_rate >>= 2 ; loops >>= 2 ; }
2174
+ if (MULTISTEPPING_LIMIT >= 2 && loops >= 2 ) { step_rate >>= 1 ; }
2132
2175
2133
2176
#endif
2134
2177
@@ -2141,6 +2184,19 @@ hal_timer_t Stepper::calc_multistep_timer_interval(uint32_t step_rate) {
2141
2184
* have been done, so it is less time critical.
2142
2185
*/
2143
2186
hal_timer_t Stepper::block_phase_isr () {
2187
+ #if DISABLED(OLD_ADAPTIVE_MULTISTEPPING)
2188
+ // If the ISR uses < 50% of MPU time, halve multi-stepping
2189
+ const hal_timer_t time_spent = HAL_timer_get_count (MF_TIMER_STEP);
2190
+ #if MULTISTEPPING_LIMIT > 1
2191
+ if (steps_per_isr > 1 && time_spent_out_isr >= time_spent_in_isr + time_spent) {
2192
+ steps_per_isr >>= 1 ;
2193
+ // ticks_nominal will need to be recalculated if we are in cruise phase
2194
+ ticks_nominal = 0 ;
2195
+ }
2196
+ #endif
2197
+ time_spent_in_isr = -time_spent; // unsigned but guaranteed to be +ve when needed
2198
+ time_spent_out_isr = 0 ;
2199
+ #endif
2144
2200
2145
2201
// If no queued movements, just wait 1ms for the next block
2146
2202
hal_timer_t interval = (STEPPER_TIMER_RATE) / 1000UL ;
0 commit comments