Parcourir la source

⚡️ Handle shared enable pins (#22824)

Scott Lahteine il y a 2 ans
Parent
révision
33e0855e2c
Aucun compte lié à l'adresse e-mail de l'auteur

+ 17
- 63
Marlin/src/MarlinCore.cpp Voir le fichier

@@ -81,10 +81,6 @@
81 81
   #endif
82 82
 #endif
83 83
 
84
-#if ENABLED(EXTENSIBLE_UI)
85
-  #include "lcd/extui/ui_api.h"
86
-#endif
87
-
88 84
 #if HAS_ETHERNET
89 85
   #include "feature/ethernet.h"
90 86
 #endif
@@ -312,48 +308,6 @@ bool pin_is_protected(const pin_t pin) {
312 308
 
313 309
 #pragma GCC diagnostic pop
314 310
 
315
-void enable_e_steppers() {
316
-  #define _ENA_E(N) ENABLE_AXIS_E##N();
317
-  REPEAT(E_STEPPERS, _ENA_E)
318
-}
319
-
320
-void enable_all_steppers() {
321
-  TERN_(AUTO_POWER_CONTROL, powerManager.power_on());
322
-  ENABLE_AXIS_X();
323
-  ENABLE_AXIS_Y();
324
-  ENABLE_AXIS_Z();
325
-  ENABLE_AXIS_I(); // Marlin 6-axis support by DerAndere (https://github.com/DerAndere1/Marlin/wiki)
326
-  ENABLE_AXIS_J();
327
-  ENABLE_AXIS_K();
328
-  enable_e_steppers();
329
-
330
-  TERN_(EXTENSIBLE_UI, ExtUI::onSteppersEnabled());
331
-}
332
-
333
-void disable_e_steppers() {
334
-  #define _DIS_E(N) DISABLE_AXIS_E##N();
335
-  REPEAT(E_STEPPERS, _DIS_E)
336
-}
337
-
338
-void disable_e_stepper(const uint8_t e) {
339
-  #define _CASE_DIS_E(N) case N: DISABLE_AXIS_E##N(); break;
340
-  switch (e) {
341
-    REPEAT(E_STEPPERS, _CASE_DIS_E)
342
-  }
343
-}
344
-
345
-void disable_all_steppers() {
346
-  DISABLE_AXIS_X();
347
-  DISABLE_AXIS_Y();
348
-  DISABLE_AXIS_Z();
349
-  DISABLE_AXIS_I();
350
-  DISABLE_AXIS_J();
351
-  DISABLE_AXIS_K();
352
-  disable_e_steppers();
353
-
354
-  TERN_(EXTENSIBLE_UI, ExtUI::onSteppersDisabled());
355
-}
356
-
357 311
 /**
358 312
  * A Print Job exists when the timer is running or SD is printing
359 313
  */
@@ -464,13 +418,13 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
464 418
         already_shutdown_steppers = true;  // L6470 SPI will consume 99% of free time without this
465 419
 
466 420
         // Individual axes will be disabled if configured
467
-        if (ENABLED(DISABLE_INACTIVE_X)) DISABLE_AXIS_X();
468
-        if (ENABLED(DISABLE_INACTIVE_Y)) DISABLE_AXIS_Y();
469
-        if (ENABLED(DISABLE_INACTIVE_Z)) DISABLE_AXIS_Z();
470
-        if (ENABLED(DISABLE_INACTIVE_I)) DISABLE_AXIS_I();
471
-        if (ENABLED(DISABLE_INACTIVE_J)) DISABLE_AXIS_J();
472
-        if (ENABLED(DISABLE_INACTIVE_K)) DISABLE_AXIS_K();
473
-        if (ENABLED(DISABLE_INACTIVE_E)) disable_e_steppers();
421
+        TERN_(DISABLE_INACTIVE_X, stepper.disable_axis(X_AXIS));
422
+        TERN_(DISABLE_INACTIVE_Y, stepper.disable_axis(Y_AXIS));
423
+        TERN_(DISABLE_INACTIVE_Z, stepper.disable_axis(Z_AXIS));
424
+        TERN_(DISABLE_INACTIVE_I, stepper.disable_axis(I_AXIS));
425
+        TERN_(DISABLE_INACTIVE_J, stepper.disable_axis(J_AXIS));
426
+        TERN_(DISABLE_INACTIVE_K, stepper.disable_axis(K_AXIS));
427
+        TERN_(DISABLE_INACTIVE_E, stepper.disable_e_steppers());
474 428
 
475 429
         TERN_(AUTO_BED_LEVELING_UBL, ubl.steppers_were_disabled());
476 430
       }
@@ -689,13 +643,13 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
689 643
       #if ENABLED(SWITCHING_EXTRUDER)
690 644
         bool oldstatus;
691 645
         switch (active_extruder) {
692
-          default: oldstatus = E0_ENABLE_READ(); ENABLE_AXIS_E0(); break;
646
+          default: oldstatus = stepper.AXIS_IS_ENABLED(E_AXIS, 0); stepper.ENABLE_EXTRUDER(0); break;
693 647
           #if E_STEPPERS > 1
694
-            case 2: case 3: oldstatus = E1_ENABLE_READ(); ENABLE_AXIS_E1(); break;
648
+            case 2: case 3: oldstatus = stepper.AXIS_IS_ENABLED(E_AXIS, 1); stepper.ENABLE_EXTRUDER(1); break;
695 649
             #if E_STEPPERS > 2
696
-              case 4: case 5: oldstatus = E2_ENABLE_READ(); ENABLE_AXIS_E2(); break;
650
+              case 4: case 5: oldstatus = stepper.AXIS_IS_ENABLED(E_AXIS, 2); stepper.ENABLE_EXTRUDER(2); break;
697 651
               #if E_STEPPERS > 3
698
-                case 6: case 7: oldstatus = E3_ENABLE_READ(); ENABLE_AXIS_E3(); break;
652
+                case 6: case 7: oldstatus = stepper.AXIS_IS_ENABLED(E_AXIS, 3); stepper.ENABLE_EXTRUDER(3); break;
699 653
               #endif // E_STEPPERS > 3
700 654
             #endif // E_STEPPERS > 2
701 655
           #endif // E_STEPPERS > 1
@@ -704,7 +658,7 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
704 658
         bool oldstatus;
705 659
         switch (active_extruder) {
706 660
           default:
707
-          #define _CASE_EN(N) case N: oldstatus = E##N##_ENABLE_READ(); ENABLE_AXIS_E##N(); break;
661
+          #define _CASE_EN(N) case N: oldstatus = stepper.AXIS_IS_ENABLED(E_AXIS, N); stepper.ENABLE_EXTRUDER(N); break;
708 662
           REPEAT(E_STEPPERS, _CASE_EN);
709 663
         }
710 664
       #endif
@@ -718,17 +672,17 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
718 672
 
719 673
       #if ENABLED(SWITCHING_EXTRUDER)
720 674
         switch (active_extruder) {
721
-          default: oldstatus = E0_ENABLE_WRITE(oldstatus); break;
675
+          default: if (oldstatus) stepper.ENABLE_EXTRUDER(0); else stepper.DISABLE_EXTRUDER(0); break;
722 676
           #if E_STEPPERS > 1
723
-            case 2: case 3: oldstatus = E1_ENABLE_WRITE(oldstatus); break;
677
+            case 2: case 3: if (oldstatus) stepper.ENABLE_EXTRUDER(1); else stepper.DISABLE_EXTRUDER(1); break;
724 678
             #if E_STEPPERS > 2
725
-              case 4: case 5: oldstatus = E2_ENABLE_WRITE(oldstatus); break;
679
+              case 4: case 5: if (oldstatus) stepper.ENABLE_EXTRUDER(2); else stepper.DISABLE_EXTRUDER(2); break;
726 680
             #endif // E_STEPPERS > 2
727 681
           #endif // E_STEPPERS > 1
728 682
         }
729 683
       #else // !SWITCHING_EXTRUDER
730 684
         switch (active_extruder) {
731
-          #define _CASE_RESTORE(N) case N: E##N##_ENABLE_WRITE(oldstatus); break;
685
+          #define _CASE_RESTORE(N) case N: if (oldstatus) stepper.ENABLE_EXTRUDER(N); else stepper.DISABLE_EXTRUDER(N); break;
732 686
           REPEAT(E_STEPPERS, _CASE_RESTORE);
733 687
         }
734 688
       #endif // !SWITCHING_EXTRUDER
@@ -940,7 +894,7 @@ void minkill(const bool steppers_off/*=false*/) {
940 894
   TERN_(HAS_CUTTER, cutter.kill());  // Reiterate cutter shutdown
941 895
 
942 896
   // Power off all steppers (for M112) or just the E steppers
943
-  steppers_off ? disable_all_steppers() : disable_e_steppers();
897
+  steppers_off ? stepper.disable_all_steppers() : stepper.disable_e_steppers();
944 898
 
945 899
   TERN_(PSU_CONTROL, powerManager.power_off());
946 900
 

+ 0
- 9
Marlin/src/MarlinCore.h Voir le fichier

@@ -38,15 +38,6 @@ inline void idle_no_sleep() { idle(true); }
38 38
   extern bool G38_did_trigger;      // Flag from the ISR to indicate the endstop changed
39 39
 #endif
40 40
 
41
-/**
42
- * The axis order in all axis related arrays is X, Y, Z, E
43
- */
44
-void enable_e_steppers();
45
-void enable_all_steppers();
46
-void disable_e_stepper(const uint8_t e);
47
-void disable_e_steppers();
48
-void disable_all_steppers();
49
-
50 41
 void kill(PGM_P const lcd_error=nullptr, PGM_P const lcd_component=nullptr, const bool steppers_off=false);
51 42
 void minkill(const bool steppers_off=false);
52 43
 

+ 3
- 24
Marlin/src/feature/controllerfan.cpp Voir le fichier

@@ -25,7 +25,7 @@
25 25
 #if ENABLED(USE_CONTROLLER_FAN)
26 26
 
27 27
 #include "controllerfan.h"
28
-#include "../module/stepper/indirection.h"
28
+#include "../module/stepper.h"
29 29
 #include "../module/temperature.h"
30 30
 
31 31
 ControllerFan controllerFan;
@@ -54,33 +54,12 @@ void ControllerFan::update() {
54 54
   if (ELAPSED(ms, nextMotorCheck)) {
55 55
     nextMotorCheck = ms + 2500UL; // Not a time critical function, so only check every 2.5s
56 56
 
57
-    #define MOTOR_IS_ON(A,B) (A##_ENABLE_READ() == bool(B##_ENABLE_ON))
58
-    #define _OR_ENABLED_E(N) || MOTOR_IS_ON(E##N,E)
59
-
60
-    const bool motor_on = (
61
-      ( DISABLED(CONTROLLER_FAN_IGNORE_Z) &&
62
-        (    MOTOR_IS_ON(Z,Z)
63
-          || TERN0(HAS_Z2_ENABLE, MOTOR_IS_ON(Z2,Z))
64
-          || TERN0(HAS_Z3_ENABLE, MOTOR_IS_ON(Z3,Z))
65
-          || TERN0(HAS_Z4_ENABLE, MOTOR_IS_ON(Z4,Z))
66
-        )
67
-      ) || (
68
-        DISABLED(CONTROLLER_FAN_USE_Z_ONLY) &&
69
-        (    MOTOR_IS_ON(X,X) || MOTOR_IS_ON(Y,Y)
70
-          || TERN0(HAS_X2_ENABLE, MOTOR_IS_ON(X2,X))
71
-          || TERN0(HAS_Y2_ENABLE, MOTOR_IS_ON(Y2,Y))
72
-          #if E_STEPPERS
73
-            REPEAT(E_STEPPERS, _OR_ENABLED_E)
74
-          #endif
75
-        )
76
-      )
77
-    );
78
-
79 57
     // If any triggers for the controller fan are true...
80 58
     //   - At least one stepper driver is enabled
81 59
     //   - The heated bed is enabled
82 60
     //   - TEMP_SENSOR_BOARD is reporting >= CONTROLLER_FAN_MIN_BOARD_TEMP
83
-    if ( motor_on
61
+    const ena_mask_t axis_mask = TERN(CONTROLLER_FAN_USE_Z_ONLY, _BV(Z_AXIS), ~TERN0(CONTROLLER_FAN_IGNORE_Z, _BV(Z_AXIS)));
62
+    if ( (stepper.axis_enabled.bits & axis_mask)
84 63
       || TERN0(HAS_HEATED_BED, thermalManager.temp_bed.soft_pwm_amount > 0)
85 64
       || TERN0(HAS_CONTROLLER_FAN_MIN_BOARD_TEMP, thermalManager.wholeDegBoard() >= CONTROLLER_FAN_MIN_BOARD_TEMP)
86 65
     ) lastMotorOn = ms; //... set time to NOW so the fan will turn on

+ 2
- 2
Marlin/src/feature/fwretract.cpp Voir le fichier

@@ -75,7 +75,7 @@ void FWRetract::reset() {
75 75
 
76 76
   LOOP_L_N(i, EXTRUDERS) {
77 77
     retracted[i] = false;
78
-    TERN_(HAS_MULTI_EXTRUDER, retracted_swap[i] = false);
78
+    E_TERN_(retracted_swap[i] = false);
79 79
     current_retract[i] = 0.0;
80 80
   }
81 81
 }
@@ -91,7 +91,7 @@ void FWRetract::reset() {
91 91
  * Note: Auto-retract will apply the set Z hop in addition to any Z hop
92 92
  *       included in the G-code. Use M207 Z0 to to prevent double hop.
93 93
  */
94
-void FWRetract::retract(const bool retracting OPTARG(HAS_MULTI_EXTRUDER, bool swapping/*=false*/)) {
94
+void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/)) {
95 95
   // Prevent two retracts or recovers in a row
96 96
   if (retracted[active_extruder] == retracting) return;
97 97
 

+ 1
- 1
Marlin/src/feature/fwretract.h Voir le fichier

@@ -74,7 +74,7 @@ public:
74 74
     #endif
75 75
   }
76 76
 
77
-  static void retract(const bool retracting OPTARG(HAS_MULTI_EXTRUDER, bool swapping = false));
77
+  static void retract(const bool retracting E_OPTARG(bool swapping=false));
78 78
 
79 79
   static void M207_report();
80 80
   static void M207();

+ 2
- 1
Marlin/src/feature/mmu/mmu.cpp Voir le fichier

@@ -26,6 +26,7 @@
26 26
 
27 27
 #include "../MarlinCore.h"
28 28
 #include "../module/planner.h"
29
+#include "../module/stepper.h"
29 30
 
30 31
 void mmu_init() {
31 32
   SET_OUTPUT(E_MUX0_PIN);
@@ -35,7 +36,7 @@ void mmu_init() {
35 36
 
36 37
 void select_multiplexed_stepper(const uint8_t e) {
37 38
   planner.synchronize();
38
-  disable_e_steppers();
39
+  stepper.disable_e_steppers();
39 40
   WRITE(E_MUX0_PIN, TEST(e, 0) ? HIGH : LOW);
40 41
   WRITE(E_MUX1_PIN, TEST(e, 1) ? HIGH : LOW);
41 42
   WRITE(E_MUX2_PIN, TEST(e, 2) ? HIGH : LOW);

+ 18
- 18
Marlin/src/feature/mmu/mmu2.cpp Voir le fichier

@@ -35,7 +35,7 @@ MMU2 mmu2;
35 35
 #include "../../libs/nozzle.h"
36 36
 #include "../../module/temperature.h"
37 37
 #include "../../module/planner.h"
38
-#include "../../module/stepper/indirection.h"
38
+#include "../../module/stepper.h"
39 39
 #include "../../MarlinCore.h"
40 40
 
41 41
 #if ENABLED(HOST_PROMPT_SUPPORT)
@@ -486,7 +486,7 @@ static void mmu2_not_responding() {
486 486
 
487 487
     if (index != extruder) {
488 488
 
489
-      DISABLE_AXIS_E0();
489
+      stepper.disable_extruder();
490 490
       ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1));
491 491
 
492 492
       command(MMU_CMD_T0 + index);
@@ -495,7 +495,7 @@ static void mmu2_not_responding() {
495 495
       if (load_to_gears()) {
496 496
         extruder = index; // filament change is finished
497 497
         active_extruder = 0;
498
-        ENABLE_AXIS_E0();
498
+        stepper.enable_extruder();
499 499
         SERIAL_ECHO_MSG(STR_ACTIVE_EXTRUDER, extruder);
500 500
       }
501 501
       ui.reset_status();
@@ -531,13 +531,13 @@ static void mmu2_not_responding() {
531 531
           #if ENABLED(MMU2_MENUS)
532 532
             planner.synchronize();
533 533
             const uint8_t index = mmu2_choose_filament();
534
-            DISABLE_AXIS_E0();
534
+            stepper.disable_extruder();
535 535
             command(MMU_CMD_T0 + index);
536 536
             manage_response(true, true);
537 537
 
538 538
             if (load_to_gears()) {
539 539
               mmu_loop();
540
-              ENABLE_AXIS_E0();
540
+              stepper.enable_extruder();
541 541
               extruder = index;
542 542
               active_extruder = 0;
543 543
             }
@@ -566,7 +566,7 @@ static void mmu2_not_responding() {
566 566
     set_runout_valid(false);
567 567
 
568 568
     if (index != extruder) {
569
-      DISABLE_AXIS_E0();
569
+      stepper.disable_extruder();
570 570
       if (FILAMENT_PRESENT()) {
571 571
         DEBUG_ECHOLNPGM("Unloading\n");
572 572
         mmu_loading_flag = false;
@@ -582,7 +582,7 @@ static void mmu2_not_responding() {
582 582
       extruder = index;
583 583
       active_extruder = 0;
584 584
 
585
-      ENABLE_AXIS_E0();
585
+      stepper.enable_extruder();
586 586
       SERIAL_ECHO_MSG(STR_ACTIVE_EXTRUDER, extruder);
587 587
 
588 588
       ui.reset_status();
@@ -620,14 +620,14 @@ static void mmu2_not_responding() {
620 620
         #if ENABLED(MMU2_MENUS)
621 621
           planner.synchronize();
622 622
           uint8_t index = mmu2_choose_filament();
623
-          DISABLE_AXIS_E0();
623
+          stepper.disable_extruder();
624 624
           command(MMU_CMD_T0 + index);
625 625
           manage_response(true, true);
626 626
           mmu_continue_loading();
627 627
           command(MMU_CMD_C0);
628 628
           mmu_loop();
629 629
 
630
-          ENABLE_AXIS_E0();
630
+          stepper.enable_extruder();
631 631
           extruder = index;
632 632
           active_extruder = 0;
633 633
         #else
@@ -670,14 +670,14 @@ static void mmu2_not_responding() {
670 670
     set_runout_valid(false);
671 671
 
672 672
     if (index != extruder) {
673
-      DISABLE_AXIS_E0();
673
+      stepper.disable_extruder();
674 674
       ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1));
675 675
       command(MMU_CMD_T0 + index);
676 676
       manage_response(true, true);
677 677
       command(MMU_CMD_C0);
678 678
       extruder = index; //filament change is finished
679 679
       active_extruder = 0;
680
-      ENABLE_AXIS_E0();
680
+      stepper.enable_extruder();
681 681
       SERIAL_ECHO_MSG(STR_ACTIVE_EXTRUDER, extruder);
682 682
       ui.reset_status();
683 683
     }
@@ -714,13 +714,13 @@ static void mmu2_not_responding() {
714 714
         #if ENABLED(MMU2_MENUS)
715 715
           planner.synchronize();
716 716
           uint8_t index = mmu2_choose_filament();
717
-          DISABLE_AXIS_E0();
717
+          stepper.disable_extruder();
718 718
           command(MMU_CMD_T0 + index);
719 719
           manage_response(true, true);
720 720
           command(MMU_CMD_C0);
721 721
           mmu_loop();
722 722
 
723
-          ENABLE_AXIS_E0();
723
+          stepper.enable_extruder();
724 724
           extruder = index;
725 725
           active_extruder = 0;
726 726
         #else
@@ -912,7 +912,7 @@ bool MMU2::load_filament_to_nozzle(const uint8_t index) {
912 912
     return false;
913 913
   }
914 914
 
915
-  DISABLE_AXIS_E0();
915
+  stepper.disable_extruder();
916 916
   command(MMU_CMD_T0 + index);
917 917
   manage_response(true, true);
918 918
 
@@ -950,7 +950,7 @@ bool MMU2::eject_filament(const uint8_t index, const bool recover) {
950 950
 
951 951
   LCD_MESSAGEPGM(MSG_MMU2_EJECTING_FILAMENT);
952 952
 
953
-  ENABLE_AXIS_E0();
953
+  stepper.enable_extruder();
954 954
   current_position.e -= MMU2_FILAMENTCHANGE_EJECT_FEED;
955 955
   line_to_current_position(MMM_TO_MMS(2500));
956 956
   planner.synchronize();
@@ -979,7 +979,7 @@ bool MMU2::eject_filament(const uint8_t index, const bool recover) {
979 979
 
980 980
   BUZZ(200, 404);
981 981
 
982
-  DISABLE_AXIS_E0();
982
+  stepper.disable_extruder();
983 983
 
984 984
   return true;
985 985
 }
@@ -1016,7 +1016,7 @@ bool MMU2::unload() {
1016 1016
 void MMU2::execute_extruder_sequence(const E_Step * sequence, int steps) {
1017 1017
 
1018 1018
   planner.synchronize();
1019
-  ENABLE_AXIS_E0();
1019
+  stepper.enable_extruder();
1020 1020
 
1021 1021
   const E_Step* step = sequence;
1022 1022
 
@@ -1034,7 +1034,7 @@ void MMU2::execute_extruder_sequence(const E_Step * sequence, int steps) {
1034 1034
     step++;
1035 1035
   }
1036 1036
 
1037
-  DISABLE_AXIS_E0();
1037
+  stepper.disable_extruder();
1038 1038
 }
1039 1039
 
1040 1040
 #endif // HAS_PRUSA_MMU2

+ 2
- 2
Marlin/src/feature/pause.cpp Voir le fichier

@@ -302,8 +302,8 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
302 302
  * send current back to their board, potentially frying it.
303 303
  */
304 304
 inline void disable_active_extruder() {
305
-  #if HAS_E_STEPPER_ENABLE
306
-    disable_e_stepper(active_extruder);
305
+  #if HAS_EXTRUDERS
306
+    stepper.DISABLE_EXTRUDER(active_extruder);
307 307
     safe_delay(100);
308 308
   #endif
309 309
 }

+ 4
- 18
Marlin/src/feature/power.cpp Voir le fichier

@@ -27,7 +27,7 @@
27 27
 #include "../inc/MarlinConfig.h"
28 28
 
29 29
 #include "power.h"
30
-#include "../module/stepper/indirection.h"
30
+#include "../module/stepper.h"
31 31
 #include "../MarlinCore.h"
32 32
 
33 33
 #if ENABLED(PS_OFF_SOUND)
@@ -120,6 +120,9 @@ void Power::power_off() {
120 120
    */
121 121
   bool Power::is_power_needed() {
122 122
 
123
+    // If any of the stepper drivers are enabled...
124
+    if (stepper.axis_enabled.bits) return true;
125
+
123 126
     if (printJobOngoing() || printingIsPaused()) return true;
124 127
 
125 128
     #if ENABLED(AUTO_POWER_FANS)
@@ -140,23 +143,6 @@ void Power::power_off() {
140 143
     if (TERN0(AUTO_POWER_COOLER_FAN, thermalManager.coolerfan_speed))
141 144
       return true;
142 145
 
143
-    // If any of the drivers or the bed are enabled...
144
-    if (X_ENABLE_READ() == X_ENABLE_ON || Y_ENABLE_READ() == Y_ENABLE_ON || Z_ENABLE_READ() == Z_ENABLE_ON
145
-      #if HAS_X2_ENABLE
146
-        || X2_ENABLE_READ() == X_ENABLE_ON
147
-      #endif
148
-      #if HAS_Y2_ENABLE
149
-        || Y2_ENABLE_READ() == Y_ENABLE_ON
150
-      #endif
151
-      #if HAS_Z2_ENABLE
152
-        || Z2_ENABLE_READ() == Z_ENABLE_ON
153
-      #endif
154
-      #if E_STEPPERS
155
-        #define _OR_ENABLED_E(N) || E##N##_ENABLE_READ() == E_ENABLE_ON
156
-        REPEAT(E_STEPPERS, _OR_ENABLED_E)
157
-      #endif
158
-    ) return true;
159
-
160 146
     #if HAS_HOTEND
161 147
       HOTEND_LOOP() if (thermalManager.degTargetHotend(e) > 0 || thermalManager.temp_hotend[e].soft_pwm_amount > 0) return true;
162 148
     #endif

+ 1
- 1
Marlin/src/feature/powerloss.cpp Voir le fichier

@@ -186,7 +186,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
186 186
     TERN_(GCODE_REPEAT_MARKERS, info.stored_repeat = repeat);
187 187
     TERN_(HAS_HOME_OFFSET, info.home_offset = home_offset);
188 188
     TERN_(HAS_POSITION_SHIFT, info.position_shift = position_shift);
189
-    TERN_(HAS_MULTI_EXTRUDER, info.active_extruder = active_extruder);
189
+    E_TERN_(info.active_extruder = active_extruder);
190 190
 
191 191
     #if DISABLED(NO_VOLUMETRICS)
192 192
       info.flag.volumetric_enabled = parser.volumetric_enabled;

+ 4
- 3
Marlin/src/gcode/config/M301.cpp Voir le fichier

@@ -48,10 +48,10 @@
48 48
 void GcodeSuite::M301() {
49 49
   // multi-extruder PID patch: M301 updates or prints a single extruder's PID values
50 50
   // default behavior (omitting E parameter) is to update for extruder 0 only
51
-  int8_t e = parser.byteval('E', -1); // extruder being updated
51
+  int8_t e = E_TERN0(parser.byteval('E', -1)); // extruder being updated
52 52
 
53 53
   if (!parser.seen("PID" TERN_(PID_EXTRUSION_SCALING, "CL") TERN_(PID_FAN_SCALING, "F")))
54
-    return M301_report(true, e);
54
+    return M301_report(true E_OPTARG(e));
55 55
 
56 56
   if (e == -1) e = 0;
57 57
 
@@ -78,8 +78,9 @@ void GcodeSuite::M301() {
78 78
     SERIAL_ERROR_MSG(STR_INVALID_EXTRUDER);
79 79
 }
80 80
 
81
-void GcodeSuite::M301_report(const bool forReplay/*=true*/, const int8_t eindex/*=-1*/) {
81
+void GcodeSuite::M301_report(const bool forReplay/*=true*/ E_OPTARG(const int8_t eindex/*=-1*/)) {
82 82
   report_heading(forReplay, PSTR(STR_HOTEND_PID));
83
+  IF_DISABLED(HAS_MULTI_EXTRUDER, constexpr int8_t eindex = -1);
83 84
   HOTEND_LOOP() {
84 85
     if (e == eindex || eindex == -1) {
85 86
       report_echo_start(forReplay);

+ 189
- 21
Marlin/src/gcode/control/M17_M18_M84.cpp Voir le fichier

@@ -29,29 +29,186 @@
29 29
   #include "../../feature/bedlevel/bedlevel.h"
30 30
 #endif
31 31
 
32
+#define DEBUG_OUT ENABLED(MARLIN_DEV_MODE)
33
+#include "../../core/debug_out.h"
34
+#include "../../libs/hex_print.h"
35
+
36
+inline axis_flags_t selected_axis_bits() {
37
+  axis_flags_t selected{0};
38
+  #if HAS_EXTRUDERS
39
+    if (parser.seen('E')) {
40
+      if (E_TERN0(parser.has_value())) {
41
+        const uint8_t e = parser.value_int();
42
+        if (e < EXTRUDERS)
43
+          selected.bits = _BV(INDEX_OF_AXIS(E_AXIS, e));
44
+      }
45
+      else
46
+        selected.bits = selected.e_bits();
47
+    }
48
+  #endif
49
+  selected.bits |= LINEAR_AXIS_GANG(
50
+      (parser.seen_test('X')        << X_AXIS),
51
+    | (parser.seen_test('Y')        << Y_AXIS),
52
+    | (parser.seen_test('Z')        << Z_AXIS),
53
+    | (parser.seen_test(AXIS4_NAME) << I_AXIS),
54
+    | (parser.seen_test(AXIS5_NAME) << J_AXIS),
55
+    | (parser.seen_test(AXIS6_NAME) << K_AXIS)
56
+  );
57
+  return selected;
58
+}
59
+
60
+// Enable specified axes and warn about other affected axes
61
+void do_enable(const axis_flags_t to_enable) {
62
+  const ena_mask_t was_enabled = stepper.axis_enabled.bits,
63
+                  shall_enable = to_enable.bits & ~was_enabled;
64
+
65
+  DEBUG_ECHOLNPGM("Now Enabled: ", hex_word(stepper.axis_enabled.bits), "  Enabling: ", hex_word(to_enable.bits), " | ", shall_enable);
66
+
67
+  if (!shall_enable) return;    // All specified axes already enabled?
68
+
69
+  ena_mask_t also_enabled = 0;    // Track steppers enabled due to overlap
70
+
71
+  // Enable all flagged axes
72
+  LOOP_LINEAR_AXES(a) {
73
+    if (TEST(shall_enable, a)) {
74
+      stepper.enable_axis(AxisEnum(a));         // Mark and enable the requested axis
75
+      DEBUG_ECHOLNPGM("Enabled ", axis_codes[a], " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... Enabled: ", hex_word(stepper.axis_enabled.bits));
76
+      also_enabled |= enable_overlap[a];
77
+    }
78
+  }
79
+  #if HAS_EXTRUDERS
80
+    LOOP_L_N(e, EXTRUDERS) {
81
+      const uint8_t a = INDEX_OF_AXIS(E_AXIS, e);
82
+      if (TEST(shall_enable, a)) {
83
+        stepper.ENABLE_EXTRUDER(e);
84
+        DEBUG_ECHOLNPGM("Enabled E", AS_DIGIT(e), " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... ", hex_word(stepper.axis_enabled.bits));
85
+        also_enabled |= enable_overlap[a];
86
+      }
87
+    }
88
+  #endif
89
+
90
+  if ((also_enabled &= ~(shall_enable | was_enabled))) {
91
+    SERIAL_CHAR('(');
92
+    LOOP_LINEAR_AXES(a) if (TEST(also_enabled, a)) SERIAL_CHAR(axis_codes[a], ' ');
93
+    #if HAS_EXTRUDERS
94
+      #define _EN_ALSO(N) if (TEST(also_enabled, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR('E', '0' + N, ' ');
95
+      REPEAT(EXTRUDERS, _EN_ALSO)
96
+    #endif
97
+    SERIAL_ECHOLNPGM("also enabled)");
98
+  }
99
+
100
+  DEBUG_ECHOLNPGM("Enabled Now: ", hex_word(stepper.axis_enabled.bits));
101
+}
102
+
32 103
 /**
33
- * M17: Enable stepper motors
104
+ * M17: Enable stepper motor power for one or more axes.
105
+ *      Print warnings for axes that share an ENABLE_PIN.
106
+ *
107
+ * Examples:
108
+ *
109
+ *  M17 XZ ; Enable X and Z axes
110
+ *  M17 E  ; Enable all E steppers
111
+ *  M17 E1 ; Enable just the E1 stepper
34 112
  */
35 113
 void GcodeSuite::M17() {
36 114
   if (parser.seen_axis()) {
37
-    LOGICAL_AXIS_CODE(
38
-      if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen_test('E'))) enable_e_steppers(),
39
-      if (parser.seen_test('X'))        ENABLE_AXIS_X(),
40
-      if (parser.seen_test('Y'))        ENABLE_AXIS_Y(),
41
-      if (parser.seen_test('Z'))        ENABLE_AXIS_Z(),
42
-      if (parser.seen_test(AXIS4_NAME)) ENABLE_AXIS_I(),
43
-      if (parser.seen_test(AXIS5_NAME)) ENABLE_AXIS_J(),
44
-      if (parser.seen_test(AXIS6_NAME)) ENABLE_AXIS_K()
45
-    );
115
+    if (any_enable_overlap())
116
+      do_enable(selected_axis_bits());
117
+    else {
118
+      #if HAS_EXTRUDERS
119
+        if (parser.seen('E')) {
120
+          if (parser.has_value()) {
121
+            const uint8_t e = parser.value_int();
122
+            if (e < EXTRUDERS) stepper.ENABLE_EXTRUDER(e);
123
+          }
124
+          else
125
+            stepper.enable_e_steppers();
126
+        }
127
+      #endif
128
+      LINEAR_AXIS_CODE(
129
+        if (parser.seen_test('X'))        stepper.enable_axis(X_AXIS),
130
+        if (parser.seen_test('Y'))        stepper.enable_axis(Y_AXIS),
131
+        if (parser.seen_test('Z'))        stepper.enable_axis(Z_AXIS),
132
+        if (parser.seen_test(AXIS4_NAME)) stepper.enable_axis(I_AXIS),
133
+        if (parser.seen_test(AXIS5_NAME)) stepper.enable_axis(J_AXIS),
134
+        if (parser.seen_test(AXIS6_NAME)) stepper.enable_axis(K_AXIS)
135
+      );
136
+    }
46 137
   }
47 138
   else {
48 139
     LCD_MESSAGEPGM(MSG_NO_MOVE);
49
-    enable_all_steppers();
140
+    stepper.enable_all_steppers();
50 141
   }
51 142
 }
52 143
 
144
+void try_to_disable(const axis_flags_t to_disable) {
145
+  ena_mask_t still_enabled = to_disable.bits & stepper.axis_enabled.bits;
146
+
147
+  DEBUG_ECHOLNPGM("Enabled: ", hex_word(stepper.axis_enabled.bits), " To Disable: ", hex_word(to_disable.bits), " | ", hex_word(still_enabled));
148
+
149
+  if (!still_enabled) return;
150
+
151
+  // Attempt to disable all flagged axes
152
+  LOOP_LINEAR_AXES(a)
153
+    if (TEST(to_disable.bits, a)) {
154
+      DEBUG_ECHOPGM("Try to disable ", axis_codes[a], " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... ");
155
+      if (stepper.disable_axis(AxisEnum(a))) {            // Mark the requested axis and request to disable
156
+        DEBUG_ECHOPGM("OK");
157
+        still_enabled &= ~(_BV(a) | enable_overlap[a]);   // If actually disabled, clear one or more tracked bits
158
+      }
159
+      else
160
+        DEBUG_ECHOPGM("OVERLAP");
161
+      DEBUG_ECHOLNPGM(" ... still_enabled=", hex_word(still_enabled));
162
+    }
163
+  #if HAS_EXTRUDERS
164
+    LOOP_L_N(e, EXTRUDERS) {
165
+      const uint8_t a = INDEX_OF_AXIS(E_AXIS, e);
166
+      if (TEST(to_disable.bits, a)) {
167
+        DEBUG_ECHOPGM("Try to disable E", AS_DIGIT(e), " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... ");
168
+        if (stepper.DISABLE_EXTRUDER(e)) {
169
+          DEBUG_ECHOPGM("OK");
170
+          still_enabled &= ~(_BV(a) | enable_overlap[a]);
171
+        }
172
+        else
173
+          DEBUG_ECHOPGM("OVERLAP");
174
+        DEBUG_ECHOLNPGM(" ... still_enabled=", hex_word(still_enabled));
175
+      }
176
+    }
177
+  #endif
178
+
179
+  auto overlap_warning = [](const ena_mask_t axis_bits) {
180
+    SERIAL_ECHOPGM(" not disabled. Shared with");
181
+    LOOP_LINEAR_AXES(a) if (TEST(axis_bits, a)) SERIAL_CHAR(' ', axis_codes[a]);
182
+    #if HAS_EXTRUDERS
183
+      #define _EN_STILLON(N) if (TEST(axis_bits, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR(' ', 'E', '0' + N);
184
+      REPEAT(EXTRUDERS, _EN_STILLON)
185
+    #endif
186
+    SERIAL_ECHOLNPGM(".");
187
+  };
188
+
189
+  // If any of the requested axes are still enabled, give a warning
190
+  LOOP_LINEAR_AXES(a) {
191
+    if (TEST(still_enabled, a)) {
192
+      SERIAL_CHAR(axis_codes[a]);
193
+      overlap_warning(stepper.axis_enabled.bits & enable_overlap[a]);
194
+    }
195
+  }
196
+  #if HAS_EXTRUDERS
197
+    LOOP_L_N(e, EXTRUDERS) {
198
+      const uint8_t a = INDEX_OF_AXIS(E_AXIS, e);
199
+      if (TEST(still_enabled, a)) {
200
+        SERIAL_CHAR('E', '0' + e);
201
+        overlap_warning(stepper.axis_enabled.bits & enable_overlap[a]);
202
+      }
203
+    }
204
+  #endif
205
+
206
+  DEBUG_ECHOLNPGM("Enabled Now: ", hex_word(stepper.axis_enabled.bits));
207
+}
208
+
53 209
 /**
54
- * M18, M84: Disable stepper motors
210
+ * M18, M84: Disable stepper motor power for one or more axes.
211
+ *           Print warnings for axes that share an ENABLE_PIN.
55 212
  */
56 213
 void GcodeSuite::M18_M84() {
57 214
   if (parser.seenval('S')) {
@@ -61,15 +218,26 @@ void GcodeSuite::M18_M84() {
61 218
   else {
62 219
     if (parser.seen_axis()) {
63 220
       planner.synchronize();
64
-      LOGICAL_AXIS_CODE(
65
-        if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen_test('E'))) disable_e_steppers(),
66
-        if (parser.seen_test('X'))        DISABLE_AXIS_X(),
67
-        if (parser.seen_test('Y'))        DISABLE_AXIS_Y(),
68
-        if (parser.seen_test('Z'))        DISABLE_AXIS_Z(),
69
-        if (parser.seen_test(AXIS4_NAME)) DISABLE_AXIS_I(),
70
-        if (parser.seen_test(AXIS5_NAME)) DISABLE_AXIS_J(),
71
-        if (parser.seen_test(AXIS6_NAME)) DISABLE_AXIS_K()
72
-      );
221
+      if (any_enable_overlap())
222
+        try_to_disable(selected_axis_bits());
223
+      else {
224
+        #if HAS_EXTRUDERS
225
+          if (parser.seen('E')) {
226
+            if (E_TERN0(parser.has_value()))
227
+              stepper.DISABLE_EXTRUDER(parser.value_int());
228
+            else
229
+              stepper.disable_e_steppers();
230
+          }
231
+        #endif
232
+        LINEAR_AXIS_CODE(
233
+          if (parser.seen_test('X'))        stepper.disable_axis(X_AXIS),
234
+          if (parser.seen_test('Y'))        stepper.disable_axis(Y_AXIS),
235
+          if (parser.seen_test('Z'))        stepper.disable_axis(Z_AXIS),
236
+          if (parser.seen_test(AXIS4_NAME)) stepper.disable_axis(I_AXIS),
237
+          if (parser.seen_test(AXIS5_NAME)) stepper.disable_axis(J_AXIS),
238
+          if (parser.seen_test(AXIS6_NAME)) stepper.disable_axis(K_AXIS)
239
+        );
240
+      }
73 241
     }
74 242
     else
75 243
       planner.finish_and_disable();

+ 1
- 1
Marlin/src/gcode/feature/fwretract/G10_G11.cpp Voir le fichier

@@ -32,7 +32,7 @@
32 32
  * G10 - Retract filament according to settings of M207
33 33
  *       TODO: Handle 'G10 P' for tool settings and 'G10 L' for workspace settings
34 34
  */
35
-void GcodeSuite::G10() { fwretract.retract(true OPTARG(HAS_MULTI_EXTRUDER, parser.boolval('S'))); }
35
+void GcodeSuite::G10() { fwretract.retract(true E_OPTARG(parser.boolval('S'))); }
36 36
 
37 37
 /**
38 38
  * G11 - Recover filament according to settings of M208

+ 1
- 1
Marlin/src/gcode/gcode.h Voir le fichier

@@ -879,7 +879,7 @@ private:
879 879
 
880 880
   #if ENABLED(PIDTEMP)
881 881
     static void M301();
882
-    static void M301_report(const bool forReplay=true, const int8_t eindex=-1);
882
+    static void M301_report(const bool forReplay=true E_OPTARG(const int8_t eindex=-1));
883 883
   #endif
884 884
 
885 885
   #if ENABLED(PREVENT_COLD_EXTRUSION)

+ 9
- 1
Marlin/src/inc/Conditionals_LCD.h Voir le fichier

@@ -587,6 +587,8 @@
587 587
  *  HOTENDS      - Number of hotends, whether connected or separate
588 588
  *  E_STEPPERS   - Number of actual E stepper motors
589 589
  *  E_MANUAL     - Number of E steppers for LCD move options
590
+ *
591
+ * These defines must be simple constants for use in REPEAT, etc.
590 592
  */
591 593
 #if EXTRUDERS
592 594
   #define HAS_EXTRUDERS 1
@@ -605,9 +607,14 @@
605 607
   #undef DISABLE_E
606 608
 #endif
607 609
 
610
+#define E_OPTARG(N) OPTARG(HAS_MULTI_EXTRUDER, N)
611
+#define E_TERN_(N)  TERN_(HAS_MULTI_EXTRUDER, N)
612
+#define E_TERN0(N)  TERN0(HAS_MULTI_EXTRUDER, N)
613
+
608 614
 #if ENABLED(E_DUAL_STEPPER_DRIVERS) // E0/E1 steppers act in tandem as E0
609 615
 
610 616
   #define E_STEPPERS      2
617
+  #define E_MANUAL        1
611 618
 
612 619
 #elif ENABLED(SWITCHING_EXTRUDER)   // One stepper for every two EXTRUDERS
613 620
 
@@ -637,7 +644,8 @@
637 644
 
638 645
 #elif HAS_PRUSA_MMU2                // Průša Multi-Material Unit v2
639 646
 
640
-  #define E_STEPPERS 1
647
+  #define E_STEPPERS      1
648
+  #define E_MANUAL        1
641 649
 
642 650
 #endif
643 651
 

+ 2
- 1
Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.cpp Voir le fichier

@@ -37,6 +37,7 @@
37 37
 #include "FileNavigator.h"
38 38
 
39 39
 #include "../../../gcode/queue.h"
40
+#include "../../../module/stepper.h"
40 41
 #include "../../../sd/cardreader.h"
41 42
 #include "../../../libs/numtostr.h"
42 43
 #include "../../../MarlinCore.h"
@@ -665,7 +666,7 @@ void ChironTFT::PanelAction(uint8_t req) {
665 666
 
666 667
     case 19:   // A19 Motors off
667 668
       if (!isPrinting()) {
668
-        disable_all_steppers(); // from marlincore.h
669
+        stepper.disable_all_steppers();
669 670
         SendtoTFTLN(AC_msg_ready);
670 671
       }
671 672
       break;

+ 2
- 1
Marlin/src/lcd/extui/anycubic_i3mega/anycubic_i3mega_lcd.cpp Voir le fichier

@@ -27,6 +27,7 @@
27 27
 #include "../ui_api.h"
28 28
 
29 29
 #include "../../../libs/numtostr.h"
30
+#include "../../../module/stepper.h" // for disable_all_steppers
30 31
 #include "../../../module/motion.h"  // for quickstop_stepper, A20 read printing speed, feedrate_percentage
31 32
 #include "../../../MarlinCore.h"     // for disable_steppers
32 33
 #include "../../../inc/MarlinConfig.h"
@@ -738,7 +739,7 @@ void AnycubicTFTClass::GetCommandFromTFT() {
738 739
           case 19: // A19 stop stepper drivers - sent on stop extrude command and on turn motors off command
739 740
             if (!isPrinting()) {
740 741
               quickstop_stepper();
741
-              disable_all_steppers();
742
+              stepper.disable_all_steppers();
742 743
             }
743 744
 
744 745
             SENDLINE_PGM("");

+ 4
- 3
Marlin/src/lcd/extui/dgus_reloaded/DGUSRxHandler.cpp Voir le fichier

@@ -33,6 +33,7 @@
33 33
 #include "../../../core/language.h"
34 34
 #include "../../../module/temperature.h"
35 35
 #include "../../../module/printcounter.h"
36
+#include "../../../module/stepper.h"
36 37
 #include "../../../gcode/queue.h"
37 38
 #if ENABLED(ADVANCED_PAUSE_FEATURE)
38 39
   #include "../../../feature/pause.h"
@@ -375,10 +376,10 @@ void DGUSRxHandler::Steppers(DGUS_VP &vp, void *data_ptr) {
375 376
 
376 377
   switch (control) {
377 378
     case DGUS_Data::Control::ENABLE:
378
-      enable_all_steppers();
379
+      stepper.enable_all_steppers();
379 380
       break;
380 381
     case DGUS_Data::Control::DISABLE:
381
-      disable_all_steppers();
382
+      stepper.disable_all_steppers();
382 383
       break;
383 384
   }
384 385
 
@@ -553,7 +554,7 @@ void DGUSRxHandler::FilamentSelect(DGUS_VP &vp, void *data_ptr) {
553 554
     default: return;
554 555
     case DGUS_Data::Extruder::CURRENT:
555 556
     case DGUS_Data::Extruder::E0:
556
-    TERN_(HAS_MULTI_EXTRUDER, case DGUS_Data::Extruder::E1:)
557
+    E_TERN_(case DGUS_Data::Extruder::E1:)
557 558
       dgus_screen_handler.filament_extruder = extruder;
558 559
       break;
559 560
   }

+ 2
- 8
Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp Voir le fichier

@@ -286,14 +286,8 @@ void DGUSTxHandler::TempMax(DGUS_VP &vp) {
286 286
 }
287 287
 
288 288
 void DGUSTxHandler::StepperStatus(DGUS_VP &vp) {
289
-  if (X_ENABLE_READ() == X_ENABLE_ON
290
-      && Y_ENABLE_READ() == Y_ENABLE_ON
291
-      && Z_ENABLE_READ() == Z_ENABLE_ON) {
292
-    dgus_display.Write((uint16_t)vp.addr, Swap16((uint16_t)DGUS_Data::Status::ENABLED));
293
-  }
294
-  else {
295
-    dgus_display.Write((uint16_t)vp.addr, Swap16((uint16_t)DGUS_Data::Status::DISABLED));
296
-  }
289
+  const bool motor_on = stepper.axis_enabled.bits & (_BV(LINEAR_AXES) - 1);
290
+  dgus_display.Write((uint16_t)vp.addr, Swap16(uint16_t(motor_on ? DGUS_Data::Status::ENABLED : DGUS_Data::Status::DISABLED)));
297 291
 }
298 292
 
299 293
 void DGUSTxHandler::StepIcons(DGUS_VP &vp) {

+ 1
- 1
Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/stress_test_screen.cpp Voir le fichier

@@ -125,7 +125,7 @@ void StressTestScreen::onIdle() {
125 125
       injectCommands_P(PSTR(
126 126
         "G0 X100 Y100 Z100 F6000\n"
127 127
         "T0\nG4 S1"
128
-        TERN_(HAS_MULTI_EXTRUDER, "\nT1\nG4 S1")
128
+        E_TERN_("\nT1\nG4 S1")
129 129
         "\nG0 X150 Y150 Z150"
130 130
       ));
131 131
     }

+ 2
- 1
Marlin/src/lcd/extui/nextion/nextion_tft.cpp Voir le fichier

@@ -33,6 +33,7 @@
33 33
 
34 34
 #include "../../../MarlinCore.h"
35 35
 #include "../../../feature/pause.h"
36
+#include "../../../module/stepper.h"
36 37
 #include "../../../gcode/queue.h"
37 38
 #include "../../../libs/numtostr.h"
38 39
 #include "../../../sd/cardreader.h"
@@ -536,7 +537,7 @@ void NextionTFT::PanelAction(uint8_t req) {
536 537
 
537 538
     case 57: // Disable Motors
538 539
       if (!isPrinting()) {
539
-        disable_all_steppers(); // from marlincore.h
540
+        stepper.disable_all_steppers();
540 541
         SEND_TXT("tmppage.M117", "Motors disabled");
541 542
       }
542 543
       break;

+ 35
- 35
Marlin/src/module/planner.cpp Voir le fichier

@@ -1375,13 +1375,13 @@ void Planner::check_axes_activity() {
1375 1375
   // Disable inactive axes
1376 1376
   //
1377 1377
   LOGICAL_AXIS_CODE(
1378
-    if (TERN0(DISABLE_E, !axis_active.e)) disable_e_steppers(),
1379
-    if (TERN0(DISABLE_X, !axis_active.x)) DISABLE_AXIS_X(),
1380
-    if (TERN0(DISABLE_Y, !axis_active.y)) DISABLE_AXIS_Y(),
1381
-    if (TERN0(DISABLE_Z, !axis_active.z)) DISABLE_AXIS_Z(),
1382
-    if (TERN0(DISABLE_I, !axis_active.i)) DISABLE_AXIS_I(),
1383
-    if (TERN0(DISABLE_J, !axis_active.j)) DISABLE_AXIS_J(),
1384
-    if (TERN0(DISABLE_K, !axis_active.k)) DISABLE_AXIS_K()
1378
+    if (TERN0(DISABLE_E, !axis_active.e)) stepper.disable_e_steppers(),
1379
+    if (TERN0(DISABLE_X, !axis_active.x)) stepper.disable_axis(X_AXIS),
1380
+    if (TERN0(DISABLE_Y, !axis_active.y)) stepper.disable_axis(Y_AXIS),
1381
+    if (TERN0(DISABLE_Z, !axis_active.z)) stepper.disable_axis(Z_AXIS),
1382
+    if (TERN0(DISABLE_I, !axis_active.i)) stepper.disable_axis(I_AXIS),
1383
+    if (TERN0(DISABLE_J, !axis_active.j)) stepper.disable_axis(J_AXIS),
1384
+    if (TERN0(DISABLE_K, !axis_active.k)) stepper.disable_axis(K_AXIS)
1385 1385
   );
1386 1386
 
1387 1387
   //
@@ -1707,7 +1707,7 @@ float Planner::triggered_position_mm(const AxisEnum axis) {
1707 1707
 
1708 1708
 void Planner::finish_and_disable() {
1709 1709
   while (has_blocks_queued() || cleaning_buffer_counter) idle();
1710
-  disable_all_steppers();
1710
+  stepper.disable_all_steppers();
1711 1711
 }
1712 1712
 
1713 1713
 /**
@@ -2144,7 +2144,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
2144 2144
     block->e_to_p_pressure = baricuda_e_to_p_pressure;
2145 2145
   #endif
2146 2146
 
2147
-  TERN_(HAS_MULTI_EXTRUDER, block->extruder = extruder);
2147
+  E_TERN_(block->extruder = extruder);
2148 2148
 
2149 2149
   #if ENABLED(AUTO_POWER_CONTROL)
2150 2150
     if (LINEAR_AXIS_GANG(
@@ -2160,43 +2160,43 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
2160 2160
   // Enable active axes
2161 2161
   #if EITHER(CORE_IS_XY, MARKFORGED_XY)
2162 2162
     if (block->steps.a || block->steps.b) {
2163
-      ENABLE_AXIS_X();
2164
-      ENABLE_AXIS_Y();
2163
+      stepper.enable_axis(X_AXIS);
2164
+      stepper.enable_axis(Y_AXIS);
2165 2165
     }
2166 2166
     #if DISABLED(Z_LATE_ENABLE)
2167
-      if (block->steps.z) ENABLE_AXIS_Z();
2167
+      if (block->steps.z) stepper.enable_axis(Z_AXIS);
2168 2168
     #endif
2169 2169
   #elif CORE_IS_XZ
2170 2170
     if (block->steps.a || block->steps.c) {
2171
-      ENABLE_AXIS_X();
2172
-      ENABLE_AXIS_Z();
2171
+      stepper.enable_axis(X_AXIS);
2172
+      stepper.enable_axis(Z_AXIS);
2173 2173
     }
2174
-    if (block->steps.y) ENABLE_AXIS_Y();
2174
+    if (block->steps.y) stepper.enable_axis(Y_AXIS);
2175 2175
   #elif CORE_IS_YZ
2176 2176
     if (block->steps.b || block->steps.c) {
2177
-      ENABLE_AXIS_Y();
2178
-      ENABLE_AXIS_Z();
2177
+      stepper.enable_axis(Y_AXIS);
2178
+      stepper.enable_axis(Z_AXIS);
2179 2179
     }
2180
-    if (block->steps.x) ENABLE_AXIS_X();
2180
+    if (block->steps.x) stepper.enable_axis(X_AXIS);
2181 2181
   #else
2182 2182
     LINEAR_AXIS_CODE(
2183
-      if (block->steps.x) ENABLE_AXIS_X(),
2184
-      if (block->steps.y) ENABLE_AXIS_Y(),
2185
-      if (TERN(Z_LATE_ENABLE, 0, block->steps.z)) ENABLE_AXIS_Z(),
2186
-      if (block->steps.i) ENABLE_AXIS_I(),
2187
-      if (block->steps.j) ENABLE_AXIS_J(),
2188
-      if (block->steps.k) ENABLE_AXIS_K()
2183
+      if (block->steps.x) stepper.enable_axis(X_AXIS),
2184
+      if (block->steps.y) stepper.enable_axis(Y_AXIS),
2185
+      if (TERN(Z_LATE_ENABLE, 0, block->steps.z)) stepper.enable_axis(Z_AXIS),
2186
+      if (block->steps.i) stepper.enable_axis(I_AXIS),
2187
+      if (block->steps.j) stepper.enable_axis(J_AXIS),
2188
+      if (block->steps.k) stepper.enable_axis(K_AXIS)
2189 2189
     );
2190 2190
   #endif
2191 2191
   #if EITHER(IS_CORE, MARKFORGED_XY)
2192 2192
     #if LINEAR_AXES >= 4
2193
-      if (block->steps.i) ENABLE_AXIS_I();
2193
+      if (block->steps.i) stepper.enable_axis(I_AXIS);
2194 2194
     #endif
2195 2195
     #if LINEAR_AXES >= 5
2196
-      if (block->steps.j) ENABLE_AXIS_J();
2196
+      if (block->steps.j) stepper.enable_axis(J_AXIS);
2197 2197
     #endif
2198 2198
     #if LINEAR_AXES >= 6
2199
-      if (block->steps.k) ENABLE_AXIS_K();
2199
+      if (block->steps.k) stepper.enable_axis(K_AXIS);
2200 2200
     #endif
2201 2201
   #endif
2202 2202
 
@@ -2214,27 +2214,27 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
2214 2214
 
2215 2215
         #define ENABLE_ONE_E(N) do{ \
2216 2216
           if (E_STEPPER_INDEX(extruder) == N) { \
2217
-            ENABLE_AXIS_E##N(); \
2217
+            stepper.ENABLE_EXTRUDER(N); \
2218 2218
             g_uc_extruder_last_move[N] = (BLOCK_BUFFER_SIZE) * 2; \
2219 2219
             if ((N) == 0 && TERN0(HAS_DUPLICATION_MODE, extruder_duplication_enabled)) \
2220
-              ENABLE_AXIS_E1(); \
2220
+              stepper.ENABLE_EXTRUDER(1); \
2221 2221
           } \
2222 2222
           else if (!g_uc_extruder_last_move[N]) { \
2223
-            DISABLE_AXIS_E##N(); \
2223
+            stepper.DISABLE_EXTRUDER(N); \
2224 2224
             if ((N) == 0 && TERN0(HAS_DUPLICATION_MODE, extruder_duplication_enabled)) \
2225
-              DISABLE_AXIS_E1(); \
2225
+              stepper.DISABLE_EXTRUDER(1); \
2226 2226
           } \
2227 2227
         }while(0);
2228 2228
 
2229 2229
       #else
2230 2230
 
2231
-        #define ENABLE_ONE_E(N) ENABLE_AXIS_E##N();
2231
+        #define ENABLE_ONE_E(N) stepper.ENABLE_EXTRUDER(N);
2232 2232
 
2233 2233
       #endif
2234 2234
 
2235 2235
       REPEAT(E_STEPPERS, ENABLE_ONE_E); // (ENABLE_ONE_E must end with semicolon)
2236 2236
     }
2237
-  #endif // EXTRUDERS
2237
+  #endif // HAS_EXTRUDERS
2238 2238
 
2239 2239
   if (esteps)
2240 2240
     NOLESS(fr_mm_s, settings.min_feedrate_mm_s);
@@ -3049,7 +3049,7 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, cons
3049 3049
       FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i];
3050 3050
     #endif
3051 3051
 
3052
-    TERN_(HAS_MULTI_EXTRUDER, block->extruder = extruder);
3052
+    E_TERN_(block->extruder = extruder);
3053 3053
 
3054 3054
     block->page_idx = page_idx;
3055 3055
 
@@ -3085,7 +3085,7 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, cons
3085 3085
     // Move buffer head
3086 3086
     block_buffer_head = next_buffer_head;
3087 3087
 
3088
-    enable_all_steppers();
3088
+    stepper.enable_all_steppers();
3089 3089
     stepper.wake_up();
3090 3090
   }
3091 3091
 

+ 5
- 5
Marlin/src/module/probe.cpp Voir le fichier

@@ -251,17 +251,17 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
251 251
   void Probe::set_probing_paused(const bool dopause) {
252 252
     TERN_(PROBING_HEATERS_OFF, thermalManager.pause_heaters(dopause));
253 253
     TERN_(PROBING_FANS_OFF, thermalManager.set_fans_paused(dopause));
254
-    TERN_(PROBING_ESTEPPERS_OFF, if (dopause) disable_e_steppers());
254
+    TERN_(PROBING_ESTEPPERS_OFF, if (dopause) stepper.disable_e_steppers());
255 255
     #if ENABLED(PROBING_STEPPERS_OFF) && DISABLED(DELTA)
256 256
       static uint8_t old_trusted;
257 257
       if (dopause) {
258 258
         old_trusted = axis_trusted;
259
-        DISABLE_AXIS_X();
260
-        DISABLE_AXIS_Y();
259
+        stepper.disable_axis(X_AXIS);
260
+        stepper.disable_axis(Y_AXIS);
261 261
       }
262 262
       else {
263
-        if (TEST(old_trusted, X_AXIS)) ENABLE_AXIS_X();
264
-        if (TEST(old_trusted, Y_AXIS)) ENABLE_AXIS_Y();
263
+        if (TEST(old_trusted, X_AXIS)) stepper.enable_axis(X_AXIS);
264
+        if (TEST(old_trusted, Y_AXIS)) stepper.enable_axis(Y_AXIS);
265 265
         axis_trusted = old_trusted;
266 266
       }
267 267
     #endif

+ 1
- 1
Marlin/src/module/settings.cpp Voir le fichier

@@ -3278,7 +3278,7 @@ void MarlinSettings::reset() {
3278 3278
     //
3279 3279
     // Tool-changing Parameters
3280 3280
     //
3281
-    TERN_(HAS_MULTI_EXTRUDER, gcode.M217_report(forReplay));
3281
+    E_TERN_(gcode.M217_report(forReplay));
3282 3282
 
3283 3283
     //
3284 3284
     // Backlash Compensation

+ 107
- 24
Marlin/src/module/stepper.cpp Voir le fichier

@@ -123,6 +123,10 @@ Stepper stepper; // Singleton
123 123
   bool L64XX_OK_to_power_up = false;  // flag to keep L64xx steppers powered down after a reset or power up
124 124
 #endif
125 125
 
126
+#if ENABLED(AUTO_POWER_CONTROL)
127
+  #include "../feature/power.h"
128
+#endif
129
+
126 130
 #if ENABLED(POWER_LOSS_RECOVERY)
127 131
   #include "../feature/powerloss.h"
128 132
 #endif
@@ -131,6 +135,10 @@ Stepper stepper; // Singleton
131 135
   #include "../feature/spindle_laser.h"
132 136
 #endif
133 137
 
138
+#if ENABLED(EXTENSIBLE_UI)
139
+  #include "../lcd/extui/ui_api.h"
140
+#endif
141
+
134 142
 // public:
135 143
 
136 144
 #if EITHER(HAS_EXTRA_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
@@ -145,6 +153,8 @@ Stepper stepper; // Singleton
145 153
   #endif
146 154
 #endif
147 155
 
156
+axis_flags_t Stepper::axis_enabled; // {0}
157
+
148 158
 // private:
149 159
 
150 160
 block_t* Stepper::current_block; // (= nullptr) A pointer to the block currently being traced
@@ -473,6 +483,89 @@ xyze_int8_t Stepper::count_direction{0};
473 483
   #define DIR_WAIT_AFTER()
474 484
 #endif
475 485
 
486
+void Stepper::enable_axis(const AxisEnum axis) {
487
+  #define _CASE_ENABLE(N) case N##_AXIS: ENABLE_AXIS_##N(); break;
488
+  switch (axis) {
489
+    LINEAR_AXIS_CODE(
490
+      _CASE_ENABLE(X), _CASE_ENABLE(Y), _CASE_ENABLE(Z),
491
+      _CASE_ENABLE(I), _CASE_ENABLE(J), _CASE_ENABLE(K)
492
+    );
493
+    default: break;
494
+  }
495
+  mark_axis_enabled(axis);
496
+}
497
+
498
+bool Stepper::disable_axis(const AxisEnum axis) {
499
+  mark_axis_disabled(axis);
500
+  // If all the axes that share the enabled bit are disabled
501
+  const bool can_disable = can_axis_disable(axis);
502
+  if (can_disable) {
503
+    #define _CASE_DISABLE(N) case N##_AXIS: DISABLE_AXIS_##N(); break;
504
+    switch (axis) {
505
+      LINEAR_AXIS_CODE(
506
+        _CASE_DISABLE(X), _CASE_DISABLE(Y), _CASE_DISABLE(Z),
507
+        _CASE_DISABLE(I), _CASE_DISABLE(J), _CASE_DISABLE(K)
508
+      );
509
+      default: break;
510
+    }
511
+  }
512
+  return can_disable;
513
+}
514
+
515
+#if HAS_EXTRUDERS
516
+
517
+  void Stepper::enable_extruder(E_TERN_(const uint8_t eindex)) {
518
+    IF_DISABLED(HAS_MULTI_EXTRUDER, constexpr uint8_t eindex = 0);
519
+    #define _CASE_ENA_E(N) case N: ENABLE_AXIS_E##N(); mark_axis_enabled(E_AXIS E_OPTARG(eindex)); break;
520
+    switch (eindex) {
521
+      REPEAT(E_STEPPERS, _CASE_ENA_E)
522
+    }
523
+  }
524
+
525
+  bool Stepper::disable_extruder(E_TERN_(const uint8_t eindex)) {
526
+    IF_DISABLED(HAS_MULTI_EXTRUDER, constexpr uint8_t eindex = 0);
527
+    mark_axis_disabled(E_AXIS E_OPTARG(eindex));
528
+    const bool can_disable = can_axis_disable(E_AXIS E_OPTARG(eindex));
529
+    if (can_disable) {
530
+      #define _CASE_DIS_E(N) case N: DISABLE_AXIS_E##N(); break;
531
+      switch (eindex) { REPEAT(E_STEPPERS, _CASE_DIS_E) }
532
+    }
533
+    return can_disable;
534
+  }
535
+
536
+  void Stepper::enable_e_steppers() {
537
+    #define _ENA_E(N) ENABLE_EXTRUDER(N);
538
+    REPEAT(EXTRUDERS, _ENA_E)
539
+  }
540
+
541
+  void Stepper::disable_e_steppers() {
542
+    #define _DIS_E(N) DISABLE_EXTRUDER(N);
543
+    REPEAT(EXTRUDERS, _DIS_E)
544
+  }
545
+
546
+#endif
547
+
548
+void Stepper::enable_all_steppers() {
549
+  TERN_(AUTO_POWER_CONTROL, powerManager.power_on());
550
+  LINEAR_AXIS_CODE(
551
+    enable_axis(X_AXIS), enable_axis(Y_AXIS), enable_axis(Z_AXIS),
552
+    enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS)
553
+  );
554
+  enable_e_steppers();
555
+
556
+  TERN_(EXTENSIBLE_UI, ExtUI::onSteppersEnabled());
557
+}
558
+
559
+void Stepper::disable_all_steppers() {
560
+  LINEAR_AXIS_CODE(
561
+    disable_axis(X_AXIS), disable_axis(Y_AXIS), disable_axis(Z_AXIS),
562
+    disable_axis(I_AXIS), disable_axis(J_AXIS), disable_axis(K_AXIS)
563
+  );
564
+  disable_e_steppers();
565
+
566
+  TERN_(EXTENSIBLE_UI, ExtUI::onSteppersDisabled());
567
+}
568
+
476 569
 /**
477 570
  * Set the stepper direction of each axis
478 571
  *
@@ -494,24 +587,12 @@ void Stepper::set_directions() {
494 587
       count_direction[_AXIS(A)] = 1;            \
495 588
     }
496 589
 
497
-  #if HAS_X_DIR
498
-    SET_STEP_DIR(X); // A
499
-  #endif
500
-  #if HAS_Y_DIR
501
-    SET_STEP_DIR(Y); // B
502
-  #endif
503
-  #if HAS_Z_DIR
504
-    SET_STEP_DIR(Z); // C
505
-  #endif
506
-  #if HAS_I_DIR
507
-    SET_STEP_DIR(I);
508
-  #endif
509
-  #if HAS_J_DIR
510
-    SET_STEP_DIR(J);
511
-  #endif
512
-  #if HAS_K_DIR
513
-    SET_STEP_DIR(K);
514
-  #endif
590
+  TERN_(HAS_X_DIR, SET_STEP_DIR(X)); // A
591
+  TERN_(HAS_Y_DIR, SET_STEP_DIR(Y)); // B
592
+  TERN_(HAS_Z_DIR, SET_STEP_DIR(Z)); // C
593
+  TERN_(HAS_I_DIR, SET_STEP_DIR(I));
594
+  TERN_(HAS_J_DIR, SET_STEP_DIR(J));
595
+  TERN_(HAS_K_DIR, SET_STEP_DIR(K));
515 596
 
516 597
   #if DISABLED(LIN_ADVANCE)
517 598
     #if ENABLED(MIXING_EXTRUDER)
@@ -2204,7 +2285,7 @@ uint32_t Stepper::block_phase_isr() {
2204 2285
 
2205 2286
       TERN_(MIXING_EXTRUDER, mixer.stepper_setup(current_block->b_color));
2206 2287
 
2207
-      TERN_(HAS_MULTI_EXTRUDER, stepper_extruder = current_block->extruder);
2288
+      E_TERN_(stepper_extruder = current_block->extruder);
2208 2289
 
2209 2290
       // Initialize the trapezoid generator from the current block.
2210 2291
       #if ENABLED(LIN_ADVANCE)
@@ -2227,7 +2308,7 @@ uint32_t Stepper::block_phase_isr() {
2227 2308
         || current_block->direction_bits != last_direction_bits
2228 2309
         || TERN(MIXING_EXTRUDER, false, stepper_extruder != last_moved_extruder)
2229 2310
       ) {
2230
-        TERN_(HAS_MULTI_EXTRUDER, last_moved_extruder = stepper_extruder);
2311
+        E_TERN_(last_moved_extruder = stepper_extruder);
2231 2312
         TERN_(HAS_L64XX, L64XX_OK_to_power_up = true);
2232 2313
         set_directions(current_block->direction_bits);
2233 2314
       }
@@ -2276,7 +2357,7 @@ uint32_t Stepper::block_phase_isr() {
2276 2357
         // If delayed Z enable, enable it now. This option will severely interfere with
2277 2358
         // timing between pulses when chaining motion between blocks, and it could lead
2278 2359
         // to lost steps in both X and Y axis, so avoid using it unless strictly necessary!!
2279
-        if (current_block->steps.z) ENABLE_AXIS_Z();
2360
+        if (current_block->steps.z) enable_axis(Z_AXIS);
2280 2361
       #endif
2281 2362
 
2282 2363
       // Mark the time_nominal as not calculated yet
@@ -2872,7 +2953,7 @@ void Stepper::report_positions() {
2872 2953
 
2873 2954
 #if ENABLED(BABYSTEPPING)
2874 2955
 
2875
-  #define _ENABLE_AXIS(AXIS) ENABLE_AXIS_## AXIS()
2956
+  #define _ENABLE_AXIS(A) enable_axis(_AXIS(A))
2876 2957
   #define _READ_DIR(AXIS) AXIS ##_DIR_READ()
2877 2958
   #define _INVERT_DIR(AXIS) INVERT_## AXIS ##_DIR
2878 2959
   #define _APPLY_DIR(AXIS, INVERT) AXIS ##_APPLY_DIR(INVERT, true)
@@ -3000,8 +3081,10 @@ void Stepper::report_positions() {
3000 3081
 
3001 3082
           const bool z_direction = direction ^ BABYSTEP_INVERT_Z;
3002 3083
 
3003
-          ENABLE_AXIS_X(); ENABLE_AXIS_Y(); ENABLE_AXIS_Z();
3004
-          ENABLE_AXIS_I(); ENABLE_AXIS_J(); ENABLE_AXIS_K();
3084
+          LINEAR_AXIS_CODE(
3085
+            enable_axis(X_AXIS), enable_axis(Y_AXIS), enable_axis(Z_AXIS),
3086
+            enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS)
3087
+          );
3005 3088
 
3006 3089
           DIR_WAIT_BEFORE();
3007 3090
 

+ 102
- 0
Marlin/src/module/stepper.h Voir le fichier

@@ -236,6 +236,71 @@
236 236
 // Perhaps DISABLE_MULTI_STEPPING should be required with ADAPTIVE_STEP_SMOOTHING.
237 237
 #define MIN_STEP_ISR_FREQUENCY (MAX_STEP_ISR_FREQUENCY_1X / 2)
238 238
 
239
+#define ENABLE_COUNT (LINEAR_AXES + E_STEPPERS)
240
+typedef IF<(ENABLE_COUNT > 8), uint16_t, uint8_t>::type ena_mask_t;
241
+
242
+// Axis flags type, for enabled state or other simple state
243
+typedef struct {
244
+  union {
245
+    ena_mask_t bits;
246
+    struct {
247
+      bool LINEAR_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1);
248
+      #if HAS_EXTRUDERS
249
+        bool LIST_N(EXTRUDERS, E0:1, E1:1, E2:1, E3:1, E4:1, E5:1, E6:1, E7:1);
250
+      #endif
251
+    };
252
+  };
253
+  constexpr ena_mask_t linear_bits() { return _BV(LINEAR_AXES) - 1; }
254
+  constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << LINEAR_AXES; }
255
+} axis_flags_t;
256
+
257
+// All the stepper enable pins
258
+constexpr pin_t ena_pins[] = {
259
+  LINEAR_AXIS_LIST(X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, I_ENABLE_PIN, J_ENABLE_PIN, K_ENABLE_PIN),
260
+  LIST_N(E_STEPPERS, E0_ENABLE_PIN, E1_ENABLE_PIN, E2_ENABLE_PIN, E3_ENABLE_PIN, E4_ENABLE_PIN, E5_ENABLE_PIN, E6_ENABLE_PIN, E7_ENABLE_PIN)
261
+};
262
+
263
+// Index of the axis or extruder element in a combined array
264
+constexpr uint8_t index_of_axis(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
265
+  return uint8_t(axis) + (E_TERN0(axis < LINEAR_AXES ? 0 : eindex));
266
+}
267
+//#define __IAX_N(N,V...)           _IAX_##N(V)
268
+//#define _IAX_N(N,V...)            __IAX_N(N,V)
269
+//#define _IAX_1(A)                 index_of_axis(A)
270
+//#define _IAX_2(A,B)               index_of_axis(A E_OPTARG(B))
271
+//#define INDEX_OF_AXIS(V...)       _IAX_N(TWO_ARGS(V),V)
272
+
273
+#define INDEX_OF_AXIS(A,V...)     index_of_axis(A E_OPTARG(V+0))
274
+
275
+// Bit mask for a matching enable pin, or 0
276
+constexpr ena_mask_t ena_same(const uint8_t a, const uint8_t b) {
277
+  return ena_pins[a] == ena_pins[b] ? _BV(b) : 0;
278
+}
279
+
280
+// Recursively get the enable overlaps mask for a given linear axis or extruder
281
+constexpr ena_mask_t ena_overlap(const uint8_t a=0, const uint8_t b=0) {
282
+  return b >= ENABLE_COUNT ? 0 : (a == b ? 0 : ena_same(a, b)) | ena_overlap(a, b + 1);
283
+}
284
+
285
+// Recursively get whether there's any overlap at all
286
+constexpr bool any_enable_overlap(const uint8_t a=0) {
287
+  return a >= ENABLE_COUNT ? false : ena_overlap(a) || any_enable_overlap(a + 1);
288
+}
289
+
290
+// Array of axes that overlap with each
291
+// TODO: Consider cases where >=2 steppers are used by a linear axis or extruder
292
+//       (e.g., CoreXY, Dual XYZ, or E with multiple steppers, etc.).
293
+constexpr ena_mask_t enable_overlap[] = {
294
+  #define _OVERLAP(N) ena_overlap(INDEX_OF_AXIS(AxisEnum(N))),
295
+  REPEAT(LINEAR_AXES, _OVERLAP)
296
+  #if HAS_EXTRUDERS
297
+    #define _E_OVERLAP(N) ena_overlap(INDEX_OF_AXIS(E_AXIS, N)),
298
+    REPEAT(E_STEPPERS, _E_OVERLAP)
299
+  #endif
300
+};
301
+
302
+//static_assert(!any_enable_overlap(), "There is some overlap.");
303
+
239 304
 //
240 305
 // Stepper class definition
241 306
 //
@@ -519,6 +584,43 @@ class Stepper {
519 584
       static void refresh_motor_power();
520 585
     #endif
521 586
 
587
+    static axis_flags_t axis_enabled;   // Axis stepper(s) ENABLED states
588
+
589
+    static inline bool axis_is_enabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
590
+      return TEST(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
591
+    }
592
+    static inline void mark_axis_enabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
593
+      SBI(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
594
+    }
595
+    static inline void mark_axis_disabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
596
+      CBI(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
597
+    }
598
+    static inline bool can_axis_disable(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
599
+      return !any_enable_overlap() || !(axis_enabled.bits & enable_overlap[INDEX_OF_AXIS(axis, eindex)]);
600
+    }
601
+
602
+    static void enable_axis(const AxisEnum axis);
603
+    static bool disable_axis(const AxisEnum axis);
604
+
605
+    #if HAS_EXTRUDERS
606
+      static void enable_extruder(E_TERN_(const uint8_t eindex=0));
607
+      static bool disable_extruder(E_TERN_(const uint8_t eindex=0));
608
+      static void enable_e_steppers();
609
+      static void disable_e_steppers();
610
+    #else
611
+      static inline void enable_extruder() {}
612
+      static inline bool disable_extruder() {}
613
+      static inline void enable_e_steppers() {}
614
+      static inline void disable_e_steppers() {}
615
+    #endif
616
+
617
+    #define  ENABLE_EXTRUDER(N)  enable_extruder(E_TERN_(N))
618
+    #define DISABLE_EXTRUDER(N) disable_extruder(E_TERN_(N))
619
+    #define AXIS_IS_ENABLED(N,V...) axis_is_enabled(N E_OPTARG(#V))
620
+
621
+    static void enable_all_steppers();
622
+    static void disable_all_steppers();
623
+
522 624
     // Update direction states for all steppers
523 625
     static void set_directions();
524 626
 

Chargement…
Annuler
Enregistrer