diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 35e7363423..6ef72d9f04 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1267,6 +1267,12 @@ #endif #endif +/** + * Multi-stepping sends steps in bursts to reduce MCU usage for high step-rates. + * This allows higher feedrates than the MCU could otherwise support. + */ +#define MULTISTEPPING_LIMIT 16 //: [1, 2, 4, 8, 16, 32, 64, 128] + /** * Adaptive Step Smoothing increases the resolution of multi-axis moves, particularly at step frequencies * below 1kHz (for AVR) or 10kHz (for ARM), where aliasing between axes in multi-axis moves causes audible diff --git a/Marlin/src/inc/Conditionals_adv.h b/Marlin/src/inc/Conditionals_adv.h index 5b303e919f..5079a93c1d 100644 --- a/Marlin/src/inc/Conditionals_adv.h +++ b/Marlin/src/inc/Conditionals_adv.h @@ -1219,3 +1219,9 @@ #undef TC_GCODE_USE_GLOBAL_Y #undef TC_GCODE_USE_GLOBAL_Z #endif + +// Multi-Stepping Limit +#ifndef MULTISTEPPING_LIMIT + #define MULTISTEPPING_LIMIT 128 + #define MULTISTEPPING_LIMIT_WARNING 1 +#endif diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 7d8f404591..5f20b205a0 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -4500,6 +4500,9 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive."); #endif #endif +// Multi-Stepping Limit +static_assert(WITHIN(MULTISTEPPING_LIMIT, 1, 128) && IS_POWER_OF_2(MULTISTEPPING_LIMIT), "MULTISTEPPING_LIMIT must be 1, 2, 4, 8, 16, 32, 64, or 128."); + // Misc. Cleanup #undef _TEST_PWM #undef _NUM_AXES_STR diff --git a/Marlin/src/inc/Warnings.cpp b/Marlin/src/inc/Warnings.cpp index 1d1426936f..184d1a08da 100644 --- a/Marlin/src/inc/Warnings.cpp +++ b/Marlin/src/inc/Warnings.cpp @@ -797,3 +797,7 @@ #if HAS_SHAPING && ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) #warning "Input Shaping for CORE / MARKFORGED kinematic axes is still experimental." #endif + +#if MULTISTEPPING_LIMIT_WARNING + #warning "MULTISTEPPING_LIMIT has been automatically set to 128. Use a lower value if the machine is slow to respond." +#endif diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 738862666f..b4c66d1fba 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -189,7 +189,10 @@ bool Stepper::abort_current_block; #endif uint32_t Stepper::acceleration_time, Stepper::deceleration_time; -uint8_t Stepper::steps_per_isr = 1; // Count of steps to perform per Stepper ISR call + +#if MULTISTEPPING_LIMIT > 1 + uint8_t Stepper::steps_per_isr = 1; // Count of steps to perform per Stepper ISR call +#endif #if ENABLED(FREEZE_FEATURE) bool Stepper::frozen; // = false @@ -2089,7 +2092,7 @@ hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) { // Get the timer interval and the number of loops to perform per tick hal_timer_t Stepper::calc_multistep_timer_interval(uint32_t step_rate) { - #if ENABLED(DISABLE_MULTI_STEPPING) + #if MULTISTEPPING_LIMIT == 1 // Just make sure the step rate is doable NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X)); @@ -2098,19 +2101,31 @@ hal_timer_t Stepper::calc_multistep_timer_interval(uint32_t step_rate) { // The stepping frequency limits for each multistepping rate static const uint32_t limit[] PROGMEM = { - ( MAX_STEP_ISR_FREQUENCY_1X ), - ( MAX_STEP_ISR_FREQUENCY_2X >> 1), - ( MAX_STEP_ISR_FREQUENCY_4X >> 2), - ( MAX_STEP_ISR_FREQUENCY_8X >> 3), - ( MAX_STEP_ISR_FREQUENCY_16X >> 4), - ( MAX_STEP_ISR_FREQUENCY_32X >> 5), - ( MAX_STEP_ISR_FREQUENCY_64X >> 6), - (MAX_STEP_ISR_FREQUENCY_128X >> 7) + ( MAX_STEP_ISR_FREQUENCY_1X ) + , ( MAX_STEP_ISR_FREQUENCY_2X >> 1) + #if MULTISTEPPING_LIMIT >= 4 + , ( MAX_STEP_ISR_FREQUENCY_4X >> 2) + #endif + #if MULTISTEPPING_LIMIT >= 8 + , ( MAX_STEP_ISR_FREQUENCY_8X >> 3) + #endif + #if MULTISTEPPING_LIMIT >= 16 + , ( MAX_STEP_ISR_FREQUENCY_16X >> 4) + #endif + #if MULTISTEPPING_LIMIT >= 32 + , ( MAX_STEP_ISR_FREQUENCY_32X >> 5) + #endif + #if MULTISTEPPING_LIMIT >= 64 + , ( MAX_STEP_ISR_FREQUENCY_64X >> 6) + #endif + #if MULTISTEPPING_LIMIT >= 128 + , (MAX_STEP_ISR_FREQUENCY_128X >> 7) + #endif }; // Find a doable step rate using multistepping uint8_t multistep = 1; - for (uint8_t i = 0; i < 7 && step_rate > uint32_t(pgm_read_dword(&limit[i])); ++i) { + for (uint8_t i = 0; i < COUNT(limit) && step_rate > uint32_t(pgm_read_dword(&limit[i])); ++i) { step_rate >>= 1; multistep <<= 1; } diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index ebd7e98aeb..820d1d9a73 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -49,9 +49,6 @@ #include "stepper/speed_lookuptable.h" #endif -// Disable multiple steps per ISR -//#define DISABLE_MULTI_STEPPING - // // Estimate the amount of time the Stepper ISR will take to execute // @@ -259,7 +256,7 @@ // The minimum step ISR rate used by ADAPTIVE_STEP_SMOOTHING to target 50% CPU usage // This does not account for the possibility of multi-stepping. -// Perhaps DISABLE_MULTI_STEPPING should be required with ADAPTIVE_STEP_SMOOTHING. +// Should a MULTISTEPPING_LIMIT of 1 should be required with ADAPTIVE_STEP_SMOOTHING? #define MIN_STEP_ISR_FREQUENCY (MAX_STEP_ISR_FREQUENCY_1X / 2) #define ENABLE_COUNT (NUM_AXES + E_STEPPERS) @@ -543,7 +540,12 @@ class Stepper { #endif static uint32_t acceleration_time, deceleration_time; // time measured in Stepper Timer ticks - static uint8_t steps_per_isr; // Count of steps to perform per Stepper ISR call + + #if MULTISTEPPING_LIMIT == 1 + static constexpr uint8_t steps_per_isr = 1; // Count of steps to perform per Stepper ISR call + #else + static uint8_t steps_per_isr; + #endif #if ENABLED(ADAPTIVE_STEP_SMOOTHING) static uint8_t oversampling_factor; // Oversampling factor (log2(multiplier)) to increase temporal resolution of axis