From 47488838579a3d686fa395cb338d381e427d8b37 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 | 9 ++++---- Marlin/src/HAL/ESP32/i2s.cpp | 32 ++++++++++++++++++++------ Marlin/src/HAL/ESP32/inc/SanityCheck.h | 2 +- Marlin/src/inc/Warnings.cpp | 8 +++++-- Marlin/src/module/stepper.cpp | 32 +++++++++++--------------- Marlin/src/module/stepper.h | 1 + 6 files changed, 51 insertions(+), 33 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 23f4430bb279..1f8883ac2d93 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 LIN_ADVANCE_K 0.00 // 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 ALLOW_LOW_EJERK // Allow a DEFAULT_EJERK value of <10. Recommended for direct drive hotends. + //#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 // 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 3ccb15989f33..a09b108f013a 100644 --- a/Marlin/src/HAL/ESP32/inc/SanityCheck.h +++ b/Marlin/src/HAL/ESP32/inc/SanityCheck.h @@ -49,6 +49,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 d0124ce686af..65174593fb5d 100644 --- a/Marlin/src/inc/Warnings.cpp +++ b/Marlin/src/inc/Warnings.cpp @@ -35,8 +35,12 @@ #warning "WARNING! Disable MARLIN_DEV_MODE for the final build!" #endif -#if LINEAR_AXES_WARNING - #warning "Note: LINEAR_AXES is now based on the *_DRIVER_TYPE settings so you can remove LINEAR_AXES from Configuration.h." +#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 // Safety Features diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index f7a5cdc025d5..7f576e72544e 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) @@ -1557,14 +1561,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 @@ -2469,18 +2466,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(); @@ -2489,11 +2487,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 c169e6357864..537f6281794c 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: