Browse Source

✨ Permit Linear Advance with I2S Streaming (#24684)

tombrazier 1 year ago
parent
commit
8e71f7add4
No account linked to committer's email address

+ 4
- 3
Marlin/Configuration_adv.h View File

@@ -2059,11 +2059,12 @@
2059 2059
  */
2060 2060
 //#define LIN_ADVANCE
2061 2061
 #if ENABLED(LIN_ADVANCE)
2062
-  //#define EXTRA_LIN_ADVANCE_K // Enable for second linear advance constants
2062
+  //#define EXTRA_LIN_ADVANCE_K // Add a second linear advance constant, configurable with M900.
2063 2063
   #define LIN_ADVANCE_K 0.22    // Unit: mm compression per 1mm/s extruder speed
2064
-  //#define LA_DEBUG            // If enabled, this will generate debug information output over USB.
2065
-  //#define EXPERIMENTAL_SCURVE // Enable this option to permit S-Curve Acceleration
2064
+  //#define LA_DEBUG            // Print debug information to serial during operation. Disable for production use.
2065
+  //#define EXPERIMENTAL_SCURVE // Allow S-Curve Acceleration to be used with LA.
2066 2066
   //#define ALLOW_LOW_EJERK     // Allow a DEFAULT_EJERK value of <10. Recommended for direct drive hotends.
2067
+  //#define EXPERIMENTAL_I2S_LA // Allow I2S_STEPPER_STREAM to be used with LA. Performance degrades as the LA step rate reaches ~20kHz.
2067 2068
 #endif
2068 2069
 
2069 2070
 // @section leveling

+ 25
- 7
Marlin/src/HAL/ESP32/i2s.cpp View File

@@ -139,22 +139,40 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) {
139 139
 }
140 140
 
141 141
 void stepperTask(void *parameter) {
142
-  uint32_t remaining = 0;
142
+  uint32_t nextMainISR = 0;
143
+  #if ENABLED(LIN_ADVANCE)
144
+    uint32_t nextAdvanceISR = Stepper::LA_ADV_NEVER;
145
+  #endif
143 146
 
144
-  while (1) {
147
+  for (;;) {
145 148
     xQueueReceive(dma.queue, &dma.current, portMAX_DELAY);
146 149
     dma.rw_pos = 0;
147 150
 
148 151
     while (dma.rw_pos < DMA_SAMPLE_COUNT) {
149 152
       // Fill with the port data post pulse_phase until the next step
150
-      if (remaining) {
153
+      if (nextMainISR && TERN1(LIN_ADVANCE, nextAdvanceISR))
151 154
         i2s_push_sample();
152
-        remaining--;
153
-      }
154
-      else {
155
+
156
+      // i2s_push_sample() is also called from Stepper::pulse_phase_isr() and Stepper::advance_isr()
157
+      // in a rare case where both are called, we need to double decrement the counters
158
+      const uint8_t push_count = 1 + (!nextMainISR && TERN0(LIN_ADVANCE, !nextAdvanceISR));
159
+
160
+      #if ENABLED(LIN_ADVANCE)
161
+        if (!nextAdvanceISR) {
162
+          Stepper::advance_isr();
163
+          nextAdvanceISR = Stepper::la_interval;
164
+        }
165
+        else if (nextAdvanceISR == Stepper::LA_ADV_NEVER)
166
+          nextAdvanceISR = Stepper::la_interval;
167
+      #endif
168
+
169
+      if (!nextMainISR) {
155 170
         Stepper::pulse_phase_isr();
156
-        remaining = Stepper::block_phase_isr();
171
+        nextMainISR = Stepper::block_phase_isr();
157 172
       }
173
+
174
+      nextMainISR -= push_count;
175
+      TERN_(LIN_ADVANCE, nextAdvanceISR -= push_count);
158 176
     }
159 177
   }
160 178
 }

+ 1
- 1
Marlin/src/HAL/ESP32/inc/SanityCheck.h View File

@@ -49,6 +49,6 @@
49 49
   #error "PULLDOWN pin mode is not available on ESP32 boards."
50 50
 #endif
51 51
 
52
-#if BOTH(I2S_STEPPER_STREAM, LIN_ADVANCE)
52
+#if BOTH(I2S_STEPPER_STREAM, LIN_ADVANCE) && DISABLED(EXPERIMENTAL_I2S_LA)
53 53
   #error "I2S stream is currently incompatible with LIN_ADVANCE."
54 54
 #endif

+ 4
- 0
Marlin/src/inc/Warnings.cpp View File

@@ -35,6 +35,10 @@
35 35
   #warning "WARNING! Disable MARLIN_DEV_MODE for the final build!"
36 36
 #endif
37 37
 
38
+#if ENABLED(LA_DEBUG)
39
+  #warning "WARNING! Disable LA_DEBUG for the final build!"
40
+#endif
41
+
38 42
 #if NUM_AXES_WARNING
39 43
   #warning "Note: NUM_AXES is now based on the *_DRIVER_TYPE settings so you can remove NUM_AXES from Configuration.h."
40 44
 #endif

+ 13
- 19
Marlin/src/module/stepper.cpp View File

@@ -137,6 +137,10 @@ Stepper stepper; // Singleton
137 137
   #include "../lcd/extui/ui_api.h"
138 138
 #endif
139 139
 
140
+#if ENABLED(I2S_STEPPER_STREAM)
141
+  #include "../HAL/ESP32/i2s.h"
142
+#endif
143
+
140 144
 // public:
141 145
 
142 146
 #if EITHER(HAS_EXTRA_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
@@ -1558,14 +1562,7 @@ void Stepper::isr() {
1558 1562
      * On AVR the ISR epilogue+prologue is estimated at 100 instructions - Give 8µs as margin
1559 1563
      * On ARM the ISR epilogue+prologue is estimated at 20 instructions - Give 1µs as margin
1560 1564
      */
1561
-    min_ticks = HAL_timer_get_count(MF_TIMER_STEP) + hal_timer_t(
1562
-      #ifdef __AVR__
1563
-        8
1564
-      #else
1565
-        1
1566
-      #endif
1567
-      * (STEPPER_TIMER_TICKS_PER_US)
1568
-    );
1565
+    min_ticks = HAL_timer_get_count(MF_TIMER_STEP) + hal_timer_t(TERN(__AVR__, 8, 1) * (STEPPER_TIMER_TICKS_PER_US));
1569 1566
 
1570 1567
     /**
1571 1568
      * NB: If for some reason the stepper monopolizes the MPU, eventually the
@@ -2472,18 +2469,19 @@ uint32_t Stepper::block_phase_isr() {
2472 2469
     // the acceleration and speed values calculated in block_phase_isr().
2473 2470
     // This helps keep LA in sync with, for example, S_CURVE_ACCELERATION.
2474 2471
     la_delta_error += la_dividend;
2475
-    if (la_delta_error >= 0) {
2472
+    const bool step_needed = la_delta_error >= 0;
2473
+    if (step_needed) {
2476 2474
       count_position.e += count_direction.e;
2477 2475
       la_advance_steps += count_direction.e;
2478 2476
       la_delta_error -= advance_divisor;
2479 2477
 
2480 2478
       // Set the STEP pulse ON
2481
-      #if ENABLED(MIXING_EXTRUDER)
2482
-        E_STEP_WRITE(mixer.get_next_stepper(), !INVERT_E_STEP_PIN);
2483
-      #else
2484
-        E_STEP_WRITE(stepper_extruder, !INVERT_E_STEP_PIN);
2485
-      #endif
2479
+      E_STEP_WRITE(TERN(MIXING_EXTRUDER, mixer.get_next_stepper(), stepper_extruder), !INVERT_E_STEP_PIN);
2480
+    }
2481
+
2482
+    TERN_(I2S_STEPPER_STREAM, i2s_push_sample());
2486 2483
 
2484
+    if (step_needed) {
2487 2485
       // Enforce a minimum duration for STEP pulse ON
2488 2486
       #if ISR_PULSE_CONTROL
2489 2487
         USING_TIMED_PULSE();
@@ -2492,11 +2490,7 @@ uint32_t Stepper::block_phase_isr() {
2492 2490
       #endif
2493 2491
 
2494 2492
       // Set the STEP pulse OFF
2495
-      #if ENABLED(MIXING_EXTRUDER)
2496
-        E_STEP_WRITE(mixer.get_stepper(), INVERT_E_STEP_PIN);
2497
-      #else
2498
-        E_STEP_WRITE(stepper_extruder, INVERT_E_STEP_PIN);
2499
-      #endif
2493
+      E_STEP_WRITE(TERN(MIXING_EXTRUDER, mixer.get_stepper(), stepper_extruder), INVERT_E_STEP_PIN);
2500 2494
     }
2501 2495
   }
2502 2496
 

+ 1
- 0
Marlin/src/module/stepper.h View File

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

Loading…
Cancel
Save