diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index cb2bdc08b4..ca4f86a834 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1447,6 +1447,7 @@ */ //#define BABYSTEPPING #if ENABLED(BABYSTEPPING) + //#define INTEGRATED_BABYSTEPPING // EXPERIMENTAL integration of babystepping into the Stepper ISR //#define BABYSTEP_WITHOUT_HOMING //#define BABYSTEP_XY // Also enable X/Y Babystepping. Not supported on DELTA! #define BABYSTEP_INVERT_Z false // Change if Z babysteps should go the other way diff --git a/Marlin/src/feature/babystep.cpp b/Marlin/src/feature/babystep.cpp index eedd8f6196..be2d1b0d2e 100644 --- a/Marlin/src/feature/babystep.cpp +++ b/Marlin/src/feature/babystep.cpp @@ -117,6 +117,10 @@ void Babystep::add_steps(const AxisEnum axis, const int16_t distance) { #if ENABLED(BABYSTEP_ALWAYS_AVAILABLE) gcode.reset_stepper_timeout(); #endif + + #if ENABLED(INTEGRATED_BABYSTEPPING) + if (has_steps()) stepper.initiateBabystepping(); + #endif } #endif // BABYSTEPPING diff --git a/Marlin/src/feature/babystep.h b/Marlin/src/feature/babystep.h index 63ea0e3e24..7f017afb55 100644 --- a/Marlin/src/feature/babystep.h +++ b/Marlin/src/feature/babystep.h @@ -23,6 +23,14 @@ #include "../inc/MarlinConfigPre.h" +#if ENABLED(INTEGRATED_BABYSTEPPING) + #define BABYSTEPS_PER_SEC 1000UL + #define BABYSTEP_TICKS ((STEPPER_TIMER_RATE) / (BABYSTEPS_PER_SEC)) +#else + #define BABYSTEPS_PER_SEC 976UL + #define BABYSTEP_TICKS ((TEMP_TIMER_RATE) / (BABYSTEPS_PER_SEC)) +#endif + #if IS_CORE || EITHER(BABYSTEP_XY, I2C_POSITION_ENCODERS) #define BS_TODO_AXIS(A) A #else @@ -56,8 +64,12 @@ public: static void add_steps(const AxisEnum axis, const int16_t distance); static void add_mm(const AxisEnum axis, const float &mm); + static inline bool has_steps() { + return steps[BS_TODO_AXIS(X_AXIS)] || steps[BS_TODO_AXIS(Y_AXIS)] || steps[BS_TODO_AXIS(Z_AXIS)]; + } + // - // Called by the Temperature ISR to + // Called by the Temperature or Stepper ISR to // apply accumulated babysteps to the axes. // static inline void task() { diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 6e0a318fcb..e898d974ed 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -217,6 +217,10 @@ uint32_t Stepper::advance_divisor = 0, #endif // LIN_ADVANCE +#if ENABLED(INTEGRATED_BABYSTEPPING) + uint32_t Stepper::nextBabystepISR = BABYSTEP_NEVER; +#endif + int32_t Stepper::ticks_nominal = -1; #if DISABLED(S_CURVE_ACCELERATION) uint32_t Stepper::acc_step_rate; // needed for deceleration start point @@ -1358,16 +1362,32 @@ void Stepper::isr() { if (!nextAdvanceISR) nextAdvanceISR = advance_isr(); // 0 = Do Linear Advance E Stepper pulses #endif + #if ENABLED(INTEGRATED_BABYSTEPPING) + const bool do_babystep = (nextBabystepISR == 0); // 0 = Do Babystepping (XY)Z pulses + if (do_babystep) nextBabystepISR = babystepping_isr(); + #endif + // ^== Time critical. NOTHING besides pulse generation should be above here!!! if (!nextMainISR) nextMainISR = block_phase_isr(); // Manage acc/deceleration, get next block + #if ENABLED(INTEGRATED_BABYSTEPPING) + if (do_babystep) // Avoid ANY stepping too soon after baby-stepping + NOLESS(nextMainISR, (BABYSTEP_TICKS) / 8) // FULL STOP for 125µs after a baby-step + + if (nextBabystepISR != BABYSTEP_NEVER) // Avoid baby-stepping too close to axis Stepping + NOLESS(nextBabystepISR, nextMainISR / 2) // TODO: Only look at axes enabled for baby-stepping + #endif + // Get the interval to the next ISR call const uint32_t interval = _MIN( - nextMainISR // Time until the next Stepper ISR + nextMainISR // Time until the next Pulse / Block phase #if ENABLED(LIN_ADVANCE) , nextAdvanceISR // Come back early for Linear Advance? #endif + #if ENABLED(INTEGRATED_BABYSTEPPING) + , nextBabystepISR // Come back early for Babystepping? + #endif , uint32_t(HAL_TIMER_TYPE_MAX) // Come back in a very long time ); @@ -1384,6 +1404,10 @@ void Stepper::isr() { if (nextAdvanceISR != LA_ADV_NEVER) nextAdvanceISR -= interval; #endif + #if ENABLED(INTEGRATED_BABYSTEPPING) + if (nextBabystepISR != BABYSTEP_NEVER) nextBabystepISR -= interval; + #endif + /** * This needs to avoid a race-condition caused by interleaving * of interrupts required by both the LA and Stepper algorithms. @@ -2043,6 +2067,16 @@ uint32_t Stepper::block_phase_isr() { #endif // LIN_ADVANCE +#if ENABLED(INTEGRATED_BABYSTEPPING) + + // Timer interrupt for baby-stepping + uint32_t Stepper::babystepping_isr() { + babystep.task(); + return babystep.has_steps() ? BABYSTEP_TICKS : BABYSTEP_NEVER; + } + +#endif + // Check if the given block is busy or not - Must not be called from ISR contexts // The current_block could change in the middle of the read by an Stepper ISR, so // we must explicitly prevent that! @@ -2511,7 +2545,10 @@ void Stepper::report_positions() { // MUST ONLY BE CALLED BY AN ISR, // No other ISR should ever interrupt this! void Stepper::babystep(const AxisEnum axis, const bool direction) { - cli(); + + #if DISABLED(INTEGRATED_BABYSTEPPING) + cli(); + #endif switch (axis) { @@ -2594,7 +2631,9 @@ void Stepper::report_positions() { default: break; } - sei(); + #if DISABLED(INTEGRATED_BABYSTEPPING) + sei(); + #endif } #endif // BABYSTEPPING diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index ed07bfd5df..9f1b9321bb 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -329,6 +329,11 @@ class Stepper { static bool LA_use_advance_lead; #endif + #if ENABLED(INTEGRATED_BABYSTEPPING) + static constexpr uint32_t BABYSTEP_NEVER = 0xFFFFFFFF; + static uint32_t nextBabystepISR; + #endif + static int32_t ticks_nominal; #if DISABLED(S_CURVE_ACCELERATION) static uint32_t acc_step_rate; // needed for deceleration start point @@ -383,6 +388,17 @@ class Stepper { FORCE_INLINE static void initiateLA() { nextAdvanceISR = 0; } #endif + #if ENABLED(INTEGRATED_BABYSTEPPING) + // The Babystepping ISR phase + static uint32_t babystepping_isr(); + FORCE_INLINE static void initiateBabystepping() { + if (nextBabystepISR == BABYSTEP_NEVER) { + nextBabystepISR = 0; + wake_up(); + } + } + #endif + // Check if the given block is busy or not - Must not be called from ISR contexts static bool is_block_busy(const block_t* const block); diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index a422912742..5bed31b1a1 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -69,7 +69,7 @@ #include "stepper.h" #endif -#if ENABLED(BABYSTEPPING) +#if ENABLED(BABYSTEPPING) && DISABLED(INTEGRATED_BABYSTEPPING) #include "../feature/babystep.h" #endif @@ -3010,7 +3010,7 @@ void Temperature::tick() { // Additional ~1KHz Tasks // - #if ENABLED(BABYSTEPPING) + #if ENABLED(BABYSTEPPING) && DISABLED(INTEGRATED_BABYSTEPPING) babystep.task(); #endif