@@ -245,6 +245,13 @@ uint32_t Stepper::advance_divisor = 0,
245
245
bool Stepper::la_active = false ;
246
246
#endif
247
247
248
+ #if ENABLED(NONLINEAR_EXTRUSION)
249
+ ne_coeff_t Stepper::ne;
250
+ ne_fix_t Stepper::ne_fix;
251
+ int32_t Stepper::ne_edividend;
252
+ uint32_t Stepper::ne_scale;
253
+ #endif
254
+
248
255
#if HAS_ZV_SHAPING
249
256
shaping_time_t ShapingQueue::now = 0 ;
250
257
#if ANY(MCU_LPC1768, MCU_LPC1769) && DISABLED(NO_LPC_ETHERNET_BUFFER)
@@ -2191,6 +2198,16 @@ hal_timer_t Stepper::calc_timer_interval(uint32_t step_rate) {
2191
2198
#endif // !CPU_32_BIT
2192
2199
}
2193
2200
2201
+ #if ENABLED(NONLINEAR_EXTRUSION)
2202
+ void Stepper::calc_nonlinear_e (uint32_t step_rate) {
2203
+ const uint32_t velocity = ne_scale * step_rate; // Scale step_rate first so all intermediate values stay in range of 8.24 fixed point math
2204
+ int32_t vd = (((int64_t )ne_fix.A * velocity) >> 24 ) + (((((int64_t )ne_fix.B * velocity) >> 24 ) * velocity) >> 24 );
2205
+ NOLESS (vd, 0 );
2206
+
2207
+ advance_dividend.e = (uint64_t (ne_fix.C + vd) * ne_edividend) >> 24 ;
2208
+ }
2209
+ #endif
2210
+
2194
2211
// Get the timer interval and the number of loops to perform per tick
2195
2212
hal_timer_t Stepper::calc_multistep_timer_interval (uint32_t step_rate) {
2196
2213
@@ -2318,6 +2335,10 @@ hal_timer_t Stepper::block_phase_isr() {
2318
2335
interval = calc_multistep_timer_interval (acc_step_rate << oversampling_factor);
2319
2336
acceleration_time += interval;
2320
2337
2338
+ #if ENABLED(NONLINEAR_EXTRUSION)
2339
+ calc_nonlinear_e (acc_step_rate << oversampling_factor);
2340
+ #endif
2341
+
2321
2342
#if ENABLED(LIN_ADVANCE)
2322
2343
if (la_active) {
2323
2344
const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0 ;
@@ -2388,6 +2409,10 @@ hal_timer_t Stepper::block_phase_isr() {
2388
2409
interval = calc_multistep_timer_interval (step_rate << oversampling_factor);
2389
2410
deceleration_time += interval;
2390
2411
2412
+ #if ENABLED(NONLINEAR_EXTRUSION)
2413
+ calc_nonlinear_e (step_rate << oversampling_factor);
2414
+ #endif
2415
+
2391
2416
#if ENABLED(LIN_ADVANCE)
2392
2417
if (la_active) {
2393
2418
const uint32_t la_step_rate = la_advance_steps > current_block->final_adv_steps ? current_block->la_advance_rate : 0 ;
@@ -2436,6 +2461,10 @@ hal_timer_t Stepper::block_phase_isr() {
2436
2461
// step_rate to timer interval and loops for the nominal speed
2437
2462
ticks_nominal = calc_multistep_timer_interval (current_block->nominal_rate << oversampling_factor);
2438
2463
2464
+ #if ENABLED(NONLINEAR_EXTRUSION)
2465
+ calc_nonlinear_e (current_block->nominal_rate << oversampling_factor);
2466
+ #endif
2467
+
2439
2468
#if ENABLED(LIN_ADVANCE)
2440
2469
if (la_active)
2441
2470
la_interval = calc_timer_interval (current_block->nominal_rate >> current_block->la_scaling );
@@ -2636,10 +2665,13 @@ hal_timer_t Stepper::block_phase_isr() {
2636
2665
acceleration_time = deceleration_time = 0 ;
2637
2666
2638
2667
#if ENABLED(ADAPTIVE_STEP_SMOOTHING)
2639
- oversampling_factor = 0 ; // Assume no axis smoothing (via oversampling)
2668
+ // Nonlinear Extrusion needs at least 2x oversampling to permit increase of E step rate
2669
+ // Otherwise assume no axis smoothing (via oversampling)
2670
+ oversampling_factor = TERN (NONLINEAR_EXTRUSION, 1 , 0 );
2671
+
2640
2672
// Decide if axis smoothing is possible
2641
- uint32_t max_rate = current_block->nominal_rate ; // Get the step event rate
2642
2673
if (TERN1 (DWIN_LCD_PROUI, hmiData.adaptiveStepSmoothing )) {
2674
+ uint32_t max_rate = current_block->nominal_rate ; // Get the step event rate
2643
2675
while (max_rate < MIN_STEP_ISR_FREQUENCY) { // As long as more ISRs are possible...
2644
2676
max_rate <<= 1 ; // Try to double the rate
2645
2677
if (max_rate < MIN_STEP_ISR_FREQUENCY) // Don't exceed the estimated ISR limit
@@ -2755,10 +2787,29 @@ hal_timer_t Stepper::block_phase_isr() {
2755
2787
acc_step_rate = current_block->initial_rate ;
2756
2788
#endif
2757
2789
2790
+ #if ENABLED(NONLINEAR_EXTRUSION)
2791
+ ne_edividend = advance_dividend.e ;
2792
+ const float scale = (float (ne_edividend) / advance_divisor) * planner.mm_per_step [E_AXIS_N (current_block->extruder )];
2793
+ ne_scale = (1L << 24 ) * scale;
2794
+ if (current_block->direction_bits .e ) {
2795
+ ne_fix.A = (1L << 24 ) * ne.A ;
2796
+ ne_fix.B = (1L << 24 ) * ne.B ;
2797
+ ne_fix.C = (1L << 24 ) * ne.C ;
2798
+ }
2799
+ else {
2800
+ ne_fix.A = ne_fix.B = 0 ;
2801
+ ne_fix.C = (1L << 24 );
2802
+ }
2803
+ #endif
2804
+
2758
2805
// Calculate the initial timer interval
2759
2806
interval = calc_multistep_timer_interval (current_block->initial_rate << oversampling_factor);
2760
2807
acceleration_time += interval;
2761
2808
2809
+ #if ENABLED(NONLINEAR_EXTRUSION)
2810
+ calc_nonlinear_e (current_block->initial_rate << oversampling_factor);
2811
+ #endif
2812
+
2762
2813
#if ENABLED(LIN_ADVANCE)
2763
2814
if (la_active) {
2764
2815
const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0 ;
0 commit comments