From c996bfddb7775f9160e33443df8c103de003339f Mon Sep 17 00:00:00 2001 From: tombrazier <68918209+tombrazier@users.noreply.github.com> Date: Fri, 2 Sep 2022 03:04:46 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Permit=20Linear=20Advance=20with=20?= =?UTF-8?q?I2S=20Streaming=20(#24684)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Marlin/Configuration_adv.h | 7 +++--- Marlin/src/HAL/ESP32/i2s.cpp | 32 ++++++++++++++++++++------ Marlin/src/HAL/ESP32/inc/SanityCheck.h | 2 +- Marlin/src/inc/Warnings.cpp | 4 ++++ Marlin/src/module/stepper.cpp | 32 +++++++++++--------------- Marlin/src/module/stepper.h | 1 + 6 files changed, 48 insertions(+), 30 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index ba3064722f11..85a69cc48322 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -2063,11 +2063,12 @@ */ //#define LIN_ADVANCE #if ENABLED(LIN_ADVANCE) - //#define EXTRA_LIN_ADVANCE_K // Enable for second linear advance constants + //#define EXTRA_LIN_ADVANCE_K // Add a second linear advance constant, configurable with M900. #define LIN_ADVANCE_K 0.22 // Unit: mm compression per 1mm/s extruder speed - //#define LA_DEBUG // If enabled, this will generate debug information output over USB. - //#define EXPERIMENTAL_SCURVE // Enable this option to permit S-Curve Acceleration + //#define LA_DEBUG // Print debug information to serial during operation. Disable for production use. + //#define EXPERIMENTAL_SCURVE // Allow S-Curve Acceleration to be used with LA. //#define ALLOW_LOW_EJERK // Allow a DEFAULT_EJERK value of <10. Recommended for direct drive hotends. + //#define EXPERIMENTAL_I2S_LA // Allow I2S_STEPPER_STREAM to be used with LA. Performance degrades as the LA step rate reaches ~20kHz. #endif // @section leveling diff --git a/Marlin/src/HAL/ESP32/i2s.cpp b/Marlin/src/HAL/ESP32/i2s.cpp index cf337eeb4622..d9bad4ec2d12 100644 --- a/Marlin/src/HAL/ESP32/i2s.cpp +++ b/Marlin/src/HAL/ESP32/i2s.cpp @@ -139,22 +139,40 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) { } void stepperTask(void *parameter) { - uint32_t remaining = 0; + uint32_t nextMainISR = 0; + #if ENABLED(LIN_ADVANCE) + uint32_t nextAdvanceISR = Stepper::LA_ADV_NEVER; + #endif - while (1) { + for (;;) { xQueueReceive(dma.queue, &dma.current, portMAX_DELAY); dma.rw_pos = 0; while (dma.rw_pos < DMA_SAMPLE_COUNT) { // Fill with the port data post pulse_phase until the next step - if (remaining) { + if (nextMainISR && TERN1(LIN_ADVANCE, nextAdvanceISR)) i2s_push_sample(); - remaining--; - } - else { + + // i2s_push_sample() is also called from Stepper::pulse_phase_isr() and Stepper::advance_isr() + // in a rare case where both are called, we need to double decrement the counters + const uint8_t push_count = 1 + (!nextMainISR && TERN0(LIN_ADVANCE, !nextAdvanceISR)); + + #if ENABLED(LIN_ADVANCE) + if (!nextAdvanceISR) { + Stepper::advance_isr(); + nextAdvanceISR = Stepper::la_interval; + } + else if (nextAdvanceISR == Stepper::LA_ADV_NEVER) + nextAdvanceISR = Stepper::la_interval; + #endif + + if (!nextMainISR) { Stepper::pulse_phase_isr(); - remaining = Stepper::block_phase_isr(); + nextMainISR = Stepper::block_phase_isr(); } + + nextMainISR -= push_count; + TERN_(LIN_ADVANCE, nextAdvanceISR -= push_count); } } } diff --git a/Marlin/src/HAL/ESP32/inc/SanityCheck.h b/Marlin/src/HAL/ESP32/inc/SanityCheck.h index 4486a0a6ee7c..8c5621f10c02 100644 --- a/Marlin/src/HAL/ESP32/inc/SanityCheck.h +++ b/Marlin/src/HAL/ESP32/inc/SanityCheck.h @@ -53,6 +53,6 @@ #error "PULLDOWN pin mode is not available on ESP32 boards." #endif -#if BOTH(I2S_STEPPER_STREAM, LIN_ADVANCE) +#if BOTH(I2S_STEPPER_STREAM, LIN_ADVANCE) && DISABLED(EXPERIMENTAL_I2S_LA) #error "I2S stream is currently incompatible with LIN_ADVANCE." #endif diff --git a/Marlin/src/inc/Warnings.cpp b/Marlin/src/inc/Warnings.cpp index a88b6e532a0c..65174593fb5d 100644 --- a/Marlin/src/inc/Warnings.cpp +++ b/Marlin/src/inc/Warnings.cpp @@ -35,6 +35,10 @@ #warning "WARNING! Disable MARLIN_DEV_MODE for the final build!" #endif +#if ENABLED(LA_DEBUG) + #warning "WARNING! Disable LA_DEBUG for the final build!" +#endif + #if NUM_AXES_WARNING #warning "Note: NUM_AXES is now based on the *_DRIVER_TYPE settings so you can remove NUM_AXES from Configuration.h." #endif diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 78c09fadefbd..4ee4c1d1a790 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -137,6 +137,10 @@ Stepper stepper; // Singleton #include "../lcd/extui/ui_api.h" #endif +#if ENABLED(I2S_STEPPER_STREAM) + #include "../HAL/ESP32/i2s.h" +#endif + // public: #if EITHER(HAS_EXTRA_ENDSTOPS, Z_STEPPER_AUTO_ALIGN) @@ -1558,14 +1562,7 @@ void Stepper::isr() { * On AVR the ISR epilogue+prologue is estimated at 100 instructions - Give 8µs as margin * On ARM the ISR epilogue+prologue is estimated at 20 instructions - Give 1µs as margin */ - min_ticks = HAL_timer_get_count(MF_TIMER_STEP) + hal_timer_t( - #ifdef __AVR__ - 8 - #else - 1 - #endif - * (STEPPER_TIMER_TICKS_PER_US) - ); + min_ticks = HAL_timer_get_count(MF_TIMER_STEP) + hal_timer_t(TERN(__AVR__, 8, 1) * (STEPPER_TIMER_TICKS_PER_US)); /** * NB: If for some reason the stepper monopolizes the MPU, eventually the @@ -2472,18 +2469,19 @@ uint32_t Stepper::block_phase_isr() { // the acceleration and speed values calculated in block_phase_isr(). // This helps keep LA in sync with, for example, S_CURVE_ACCELERATION. la_delta_error += la_dividend; - if (la_delta_error >= 0) { + const bool step_needed = la_delta_error >= 0; + if (step_needed) { count_position.e += count_direction.e; la_advance_steps += count_direction.e; la_delta_error -= advance_divisor; // Set the STEP pulse ON - #if ENABLED(MIXING_EXTRUDER) - E_STEP_WRITE(mixer.get_next_stepper(), !INVERT_E_STEP_PIN); - #else - E_STEP_WRITE(stepper_extruder, !INVERT_E_STEP_PIN); - #endif + E_STEP_WRITE(TERN(MIXING_EXTRUDER, mixer.get_next_stepper(), stepper_extruder), !INVERT_E_STEP_PIN); + } + + TERN_(I2S_STEPPER_STREAM, i2s_push_sample()); + if (step_needed) { // Enforce a minimum duration for STEP pulse ON #if ISR_PULSE_CONTROL USING_TIMED_PULSE(); @@ -2492,11 +2490,7 @@ uint32_t Stepper::block_phase_isr() { #endif // Set the STEP pulse OFF - #if ENABLED(MIXING_EXTRUDER) - E_STEP_WRITE(mixer.get_stepper(), INVERT_E_STEP_PIN); - #else - E_STEP_WRITE(stepper_extruder, INVERT_E_STEP_PIN); - #endif + E_STEP_WRITE(TERN(MIXING_EXTRUDER, mixer.get_stepper(), stepper_extruder), INVERT_E_STEP_PIN); } } diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index ccf342b573e7..729ab83266b1 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -318,6 +318,7 @@ constexpr ena_mask_t enable_overlap[] = { class Stepper { friend class KinematicSystem; friend class DeltaKinematicSystem; + friend void stepperTask(void *); public: