Permit Linear Advance with I2S Streaming (#24684)

This commit is contained in:
tombrazier 2022-09-02 03:04:46 +01:00 committed by Scott Lahteine
parent 647d459a15
commit c996bfddb7
6 changed files with 48 additions and 30 deletions

View File

@ -2063,11 +2063,12 @@
*/ */
//#define LIN_ADVANCE //#define LIN_ADVANCE
#if ENABLED(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 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 LA_DEBUG // Print debug information to serial during operation. Disable for production use.
//#define EXPERIMENTAL_SCURVE // Enable this option to permit S-Curve Acceleration //#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 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 #endif
// @section leveling // @section leveling

View File

@ -139,22 +139,40 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) {
} }
void stepperTask(void *parameter) { 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); xQueueReceive(dma.queue, &dma.current, portMAX_DELAY);
dma.rw_pos = 0; dma.rw_pos = 0;
while (dma.rw_pos < DMA_SAMPLE_COUNT) { while (dma.rw_pos < DMA_SAMPLE_COUNT) {
// Fill with the port data post pulse_phase until the next step // Fill with the port data post pulse_phase until the next step
if (remaining) { if (nextMainISR && TERN1(LIN_ADVANCE, nextAdvanceISR))
i2s_push_sample(); i2s_push_sample();
remaining--;
} // i2s_push_sample() is also called from Stepper::pulse_phase_isr() and Stepper::advance_isr()
else { // 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(); Stepper::pulse_phase_isr();
remaining = Stepper::block_phase_isr(); nextMainISR = Stepper::block_phase_isr();
} }
nextMainISR -= push_count;
TERN_(LIN_ADVANCE, nextAdvanceISR -= push_count);
} }
} }
} }

View File

@ -53,6 +53,6 @@
#error "PULLDOWN pin mode is not available on ESP32 boards." #error "PULLDOWN pin mode is not available on ESP32 boards."
#endif #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." #error "I2S stream is currently incompatible with LIN_ADVANCE."
#endif #endif

View File

@ -35,6 +35,10 @@
#warning "WARNING! Disable MARLIN_DEV_MODE for the final build!" #warning "WARNING! Disable MARLIN_DEV_MODE for the final build!"
#endif #endif
#if ENABLED(LA_DEBUG)
#warning "WARNING! Disable LA_DEBUG for the final build!"
#endif
#if NUM_AXES_WARNING #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." #warning "Note: NUM_AXES is now based on the *_DRIVER_TYPE settings so you can remove NUM_AXES from Configuration.h."
#endif #endif

View File

@ -137,6 +137,10 @@ Stepper stepper; // Singleton
#include "../lcd/extui/ui_api.h" #include "../lcd/extui/ui_api.h"
#endif #endif
#if ENABLED(I2S_STEPPER_STREAM)
#include "../HAL/ESP32/i2s.h"
#endif
// public: // public:
#if EITHER(HAS_EXTRA_ENDSTOPS, Z_STEPPER_AUTO_ALIGN) #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 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 * 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( min_ticks = HAL_timer_get_count(MF_TIMER_STEP) + hal_timer_t(TERN(__AVR__, 8, 1) * (STEPPER_TIMER_TICKS_PER_US));
#ifdef __AVR__
8
#else
1
#endif
* (STEPPER_TIMER_TICKS_PER_US)
);
/** /**
* NB: If for some reason the stepper monopolizes the MPU, eventually the * 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(). // the acceleration and speed values calculated in block_phase_isr().
// This helps keep LA in sync with, for example, S_CURVE_ACCELERATION. // This helps keep LA in sync with, for example, S_CURVE_ACCELERATION.
la_delta_error += la_dividend; 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; count_position.e += count_direction.e;
la_advance_steps += count_direction.e; la_advance_steps += count_direction.e;
la_delta_error -= advance_divisor; la_delta_error -= advance_divisor;
// Set the STEP pulse ON // Set the STEP pulse ON
#if ENABLED(MIXING_EXTRUDER) E_STEP_WRITE(TERN(MIXING_EXTRUDER, mixer.get_next_stepper(), stepper_extruder), !INVERT_E_STEP_PIN);
E_STEP_WRITE(mixer.get_next_stepper(), !INVERT_E_STEP_PIN); }
#else
E_STEP_WRITE(stepper_extruder, !INVERT_E_STEP_PIN);
#endif
TERN_(I2S_STEPPER_STREAM, i2s_push_sample());
if (step_needed) {
// Enforce a minimum duration for STEP pulse ON // Enforce a minimum duration for STEP pulse ON
#if ISR_PULSE_CONTROL #if ISR_PULSE_CONTROL
USING_TIMED_PULSE(); USING_TIMED_PULSE();
@ -2492,11 +2490,7 @@ uint32_t Stepper::block_phase_isr() {
#endif #endif
// Set the STEP pulse OFF // Set the STEP pulse OFF
#if ENABLED(MIXING_EXTRUDER) E_STEP_WRITE(TERN(MIXING_EXTRUDER, mixer.get_stepper(), stepper_extruder), INVERT_E_STEP_PIN);
E_STEP_WRITE(mixer.get_stepper(), INVERT_E_STEP_PIN);
#else
E_STEP_WRITE(stepper_extruder, INVERT_E_STEP_PIN);
#endif
} }
} }

View File

@ -318,6 +318,7 @@ constexpr ena_mask_t enable_overlap[] = {
class Stepper { class Stepper {
friend class KinematicSystem; friend class KinematicSystem;
friend class DeltaKinematicSystem; friend class DeltaKinematicSystem;
friend void stepperTask(void *);
public: public: