浏览代码

♻️ Refactor Linear / Logical / Distinct Axes (#21953)

* More patches supporting EXTRUDERS 0
* Extend types in prep for more axes
Scott Lahteine 4 年前
父节点
当前提交
dd4990252e
没有帐户链接到提交者的电子邮件
共有 43 个文件被更改,包括 1141 次插入787 次删除
  1. 5
    2
      Marlin/src/core/serial.cpp
  2. 5
    2
      Marlin/src/core/serial.h
  3. 248
    192
      Marlin/src/core/types.h
  4. 8
    0
      Marlin/src/core/utility.h
  5. 17
    26
      Marlin/src/feature/encoder_i2c.cpp
  6. 25
    9
      Marlin/src/feature/tmc_util.cpp
  7. 10
    4
      Marlin/src/feature/tmc_util.h
  8. 19
    8
      Marlin/src/gcode/calibrate/G28.cpp
  9. 8
    4
      Marlin/src/gcode/calibrate/G425.cpp
  10. 6
    4
      Marlin/src/gcode/calibrate/M425.cpp
  11. 13
    14
      Marlin/src/gcode/config/M200-M205.cpp
  12. 24
    19
      Marlin/src/gcode/config/M92.cpp
  13. 14
    10
      Marlin/src/gcode/control/M17_M18_M84.cpp
  14. 7
    5
      Marlin/src/gcode/feature/pause/G61.cpp
  15. 13
    5
      Marlin/src/gcode/feature/trinamic/M122.cpp
  16. 14
    12
      Marlin/src/gcode/gcode.cpp
  17. 23
    14
      Marlin/src/gcode/gcode.h
  18. 26
    11
      Marlin/src/gcode/geometry/G92.cpp
  19. 1
    1
      Marlin/src/gcode/host/M114.cpp
  20. 6
    4
      Marlin/src/gcode/motion/G0_G1.cpp
  21. 22
    9
      Marlin/src/gcode/motion/G2_G3.cpp
  22. 1
    1
      Marlin/src/gcode/motion/M290.cpp
  23. 2
    1
      Marlin/src/gcode/parser.cpp
  24. 1
    1
      Marlin/src/gcode/parser.h
  25. 56
    38
      Marlin/src/inc/Conditionals_LCD.h
  26. 20
    0
      Marlin/src/inc/Conditionals_adv.h
  27. 128
    121
      Marlin/src/inc/Conditionals_post.h
  28. 16
    11
      Marlin/src/inc/SanityCheck.h
  29. 4
    2
      Marlin/src/lcd/dogm/status_screen_DOGM.cpp
  30. 4
    4
      Marlin/src/lcd/extui/dgus/mks/DGUSDisplayDef.cpp
  31. 7
    3
      Marlin/src/lcd/marlinui.cpp
  32. 18
    22
      Marlin/src/lcd/menu/menu_advanced.cpp
  33. 9
    2
      Marlin/src/module/endstops.cpp
  34. 68
    34
      Marlin/src/module/motion.cpp
  35. 10
    4
      Marlin/src/module/motion.h
  36. 153
    113
      Marlin/src/module/planner.cpp
  37. 33
    17
      Marlin/src/module/planner.h
  38. 26
    20
      Marlin/src/module/settings.cpp
  39. 34
    22
      Marlin/src/module/stepper.cpp
  40. 12
    4
      Marlin/src/module/stepper.h
  41. 15
    8
      Marlin/src/module/stepper/trinamic.cpp
  42. 8
    4
      buildroot/tests/mega2560
  43. 2
    0
      buildroot/tests/rambo

+ 5
- 2
Marlin/src/core/serial.cpp 查看文件

101
   }
101
   }
102
 }
102
 }
103
 
103
 
104
-void print_pos(const_float_t x, const_float_t y, const_float_t z, PGM_P const prefix/*=nullptr*/, PGM_P const suffix/*=nullptr*/) {
104
+void print_pos(
105
+  LINEAR_AXIS_LIST(const_float_t x, const_float_t y, const_float_t z)
106
+  , PGM_P const prefix/*=nullptr*/, PGM_P const suffix/*=nullptr*/
107
+) {
105
   if (prefix) serialprintPGM(prefix);
108
   if (prefix) serialprintPGM(prefix);
106
-  SERIAL_ECHOPAIR_P(SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z);
109
+  SERIAL_ECHOPAIR_P(LIST_N(DOUBLE(LINEAR_AXES), SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z));
107
   if (suffix) serialprintPGM(suffix); else SERIAL_EOL();
110
   if (suffix) serialprintPGM(suffix); else SERIAL_EOL();
108
 }
111
 }

+ 5
- 2
Marlin/src/core/serial.h 查看文件

310
 void serial_spaces(uint8_t count);
310
 void serial_spaces(uint8_t count);
311
 
311
 
312
 void print_bin(const uint16_t val);
312
 void print_bin(const uint16_t val);
313
-void print_pos(const_float_t x, const_float_t y, const_float_t z, PGM_P const prefix=nullptr, PGM_P const suffix=nullptr);
313
+void print_pos(
314
+  LINEAR_AXIS_LIST(const_float_t x, const_float_t y, const_float_t z),
315
+  PGM_P const prefix=nullptr, PGM_P const suffix=nullptr
316
+);
314
 
317
 
315
 inline void print_pos(const xyz_pos_t &xyz, PGM_P const prefix=nullptr, PGM_P const suffix=nullptr) {
318
 inline void print_pos(const xyz_pos_t &xyz, PGM_P const prefix=nullptr, PGM_P const suffix=nullptr) {
316
-  print_pos(xyz.x, xyz.y, xyz.z, prefix, suffix);
319
+  print_pos(LINEAR_AXIS_LIST(xyz.x, xyz.y, xyz.z), prefix, suffix);
317
 }
320
 }
318
 
321
 
319
 #define SERIAL_POS(SUFFIX,VAR) do { print_pos(VAR, PSTR("  " STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n")); }while(0)
322
 #define SERIAL_POS(SUFFIX,VAR) do { print_pos(VAR, PSTR("  " STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n")); }while(0)

+ 248
- 192
Marlin/src/core/types.h 查看文件

39
 template <class L, class R>
39
 template <class L, class R>
40
 struct IF<true, L, R> { typedef L type; };
40
 struct IF<true, L, R> { typedef L type; };
41
 
41
 
42
+#define LINEAR_AXIS_GANG(V...) GANG_N(LINEAR_AXES, V)
43
+#define LINEAR_AXIS_CODE(V...) CODE_N(LINEAR_AXES, V)
44
+#define LINEAR_AXIS_LIST(V...) LIST_N(LINEAR_AXES, V)
45
+#define LINEAR_AXIS_ARRAY(V...) { LINEAR_AXIS_LIST(V) }
46
+
47
+#define LOGICAL_AXIS_GANG(E,V...) LINEAR_AXIS_GANG(V) GANG_ITEM_E(E)
48
+#define LOGICAL_AXIS_CODE(E,V...) LINEAR_AXIS_CODE(V) CODE_ITEM_E(E)
49
+#define LOGICAL_AXIS_LIST(E,V...) LINEAR_AXIS_LIST(V) LIST_ITEM_E(E)
50
+#define LOGICAL_AXIS_ARRAY(E,V...) { LOGICAL_AXIS_LIST(E,V) }
51
+
52
+#if HAS_EXTRUDERS
53
+  #define LIST_ITEM_E(N) , N
54
+  #define CODE_ITEM_E(N) ; N
55
+  #define GANG_ITEM_E(N) N
56
+#else
57
+  #define LIST_ITEM_E(N)
58
+  #define CODE_ITEM_E(N)
59
+  #define GANG_ITEM_E(N)
60
+#endif
61
+
42
 //
62
 //
43
 // Enumerated axis indices
63
 // Enumerated axis indices
44
 //
64
 //
47
 //  - X_HEAD, Y_HEAD, and Z_HEAD should be used for Steppers on Core kinematics
67
 //  - X_HEAD, Y_HEAD, and Z_HEAD should be used for Steppers on Core kinematics
48
 //
68
 //
49
 enum AxisEnum : uint8_t {
69
 enum AxisEnum : uint8_t {
50
-  X_AXIS = 0, A_AXIS = X_AXIS,
51
-  Y_AXIS = 1, B_AXIS = Y_AXIS,
52
-  Z_AXIS = 2, C_AXIS = Z_AXIS,
53
-  E_AXIS,
54
-  X_HEAD, Y_HEAD, Z_HEAD,
55
-  E0_AXIS = E_AXIS,
56
-  E1_AXIS, E2_AXIS, E3_AXIS, E4_AXIS, E5_AXIS, E6_AXIS, E7_AXIS,
70
+
71
+  // Linear axes may be controlled directly or indirectly
72
+  LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS),
73
+
74
+  // Extruder axes may be considered distinctly
75
+  #define _EN_ITEM(N) E##N##_AXIS,
76
+  REPEAT(EXTRUDERS, _EN_ITEM)
77
+  #undef _EN_ITEM
78
+
79
+  // Core also keeps toolhead directions
80
+  #if IS_CORE
81
+    X_HEAD, Y_HEAD, Z_HEAD,
82
+  #endif
83
+
84
+  // Distinct axes, including all E and Core
85
+  NUM_AXIS_ENUMS,
86
+
87
+  // Most of the time we refer only to the single E_AXIS
88
+  #if HAS_EXTRUDERS
89
+    E_AXIS = E0_AXIS,
90
+  #endif
91
+
92
+  // A, B, and C are for DELTA, SCARA, etc.
93
+  A_AXIS = X_AXIS,
94
+  #if LINEAR_AXES >= 2
95
+    B_AXIS = Y_AXIS,
96
+  #endif
97
+  #if LINEAR_AXES >= 3
98
+    C_AXIS = Z_AXIS,
99
+  #endif
100
+
101
+  // To refer to all or none
57
   ALL_AXES_ENUM = 0xFE, NO_AXIS_ENUM = 0xFF
102
   ALL_AXES_ENUM = 0xFE, NO_AXIS_ENUM = 0xFF
58
 };
103
 };
59
 
104
 
105
+typedef IF<(NUM_AXIS_ENUMS > 8), uint16_t, uint8_t>::type axis_bits_t;
106
+
60
 //
107
 //
61
 // Loop over axes
108
 // Loop over axes
62
 //
109
 //
185
 void toNative(xyze_pos_t &raw);
232
 void toNative(xyze_pos_t &raw);
186
 
233
 
187
 //
234
 //
188
-// XY coordinates, counters, etc.
235
+// Paired XY coordinates, counters, flags, etc.
189
 //
236
 //
190
 template<typename T>
237
 template<typename T>
191
 struct XYval {
238
 struct XYval {
197
   FI void set(const T px)                               { x = px; }
244
   FI void set(const T px)                               { x = px; }
198
   FI void set(const T px, const T py)                   { x = px; y = py; }
245
   FI void set(const T px, const T py)                   { x = px; y = py; }
199
   FI void set(const T (&arr)[XY])                       { x = arr[0]; y = arr[1]; }
246
   FI void set(const T (&arr)[XY])                       { x = arr[0]; y = arr[1]; }
200
-  FI void set(const T (&arr)[XYZ])                      { x = arr[0]; y = arr[1]; }
201
-  FI void set(const T (&arr)[XYZE])                     { x = arr[0]; y = arr[1]; }
202
-  #if DISTINCT_AXES > LOGICAL_AXES
203
-    FI void set(const T (&arr)[DISTINCT_AXES])          { x = arr[0]; y = arr[1]; }
247
+  #if LINEAR_AXES > XY
248
+    FI void set(const T (&arr)[LINEAR_AXES])            { x = arr[0]; y = arr[1]; }
249
+  #endif
250
+  #if LOGICAL_AXES > LINEAR_AXES
251
+    FI void set(const T (&arr)[LOGICAL_AXES])           { x = arr[0]; y = arr[1]; }
252
+    #if DISTINCT_AXES > LOGICAL_AXES
253
+      FI void set(const T (&arr)[DISTINCT_AXES])        { x = arr[0]; y = arr[1]; }
254
+    #endif
204
   #endif
255
   #endif
205
   FI void reset()                                       { x = y = 0; }
256
   FI void reset()                                       { x = y = 0; }
206
   FI T magnitude()                                const { return (T)sqrtf(x*x + y*y); }
257
   FI T magnitude()                                const { return (T)sqrtf(x*x + y*y); }
223
   FI operator XYZval<T>()                         const { return { x, y }; }
274
   FI operator XYZval<T>()                         const { return { x, y }; }
224
   FI operator XYZEval<T>()                              { return { x, y }; }
275
   FI operator XYZEval<T>()                              { return { x, y }; }
225
   FI operator XYZEval<T>()                        const { return { x, y }; }
276
   FI operator XYZEval<T>()                        const { return { x, y }; }
226
-  FI       T&  operator[](const int i)                  { return pos[i]; }
227
-  FI const T&  operator[](const int i)            const { return pos[i]; }
277
+  FI       T&  operator[](const int n)                  { return pos[n]; }
278
+  FI const T&  operator[](const int n)            const { return pos[n]; }
228
   FI XYval<T>& operator= (const T v)                    { set(v,    v   ); return *this; }
279
   FI XYval<T>& operator= (const T v)                    { set(v,    v   ); return *this; }
229
   FI XYval<T>& operator= (const XYZval<T>  &rs)         { set(rs.x, rs.y); return *this; }
280
   FI XYval<T>& operator= (const XYZval<T>  &rs)         { set(rs.x, rs.y); return *this; }
230
   FI XYval<T>& operator= (const XYZEval<T> &rs)         { set(rs.x, rs.y); return *this; }
281
   FI XYval<T>& operator= (const XYZEval<T> &rs)         { set(rs.x, rs.y); return *this; }
294
 };
345
 };
295
 
346
 
296
 //
347
 //
297
-// XYZ coordinates, counters, etc.
348
+// Linear Axes coordinates, counters, flags, etc.
298
 //
349
 //
299
 template<typename T>
350
 template<typename T>
300
 struct XYZval {
351
 struct XYZval {
301
   union {
352
   union {
302
-    struct { T x, y, z; };
303
-    struct { T a, b, c; };
304
-    T pos[3];
353
+    struct { T LINEAR_AXIS_LIST(x, y, z); };
354
+    struct { T LINEAR_AXIS_LIST(a, b, c); };
355
+    T pos[LINEAR_AXES];
305
   };
356
   };
306
   FI void set(const T px)                              { x = px; }
357
   FI void set(const T px)                              { x = px; }
307
   FI void set(const T px, const T py)                  { x = px; y = py; }
358
   FI void set(const T px, const T py)                  { x = px; y = py; }
308
-  FI void set(const T px, const T py, const T pz)      { x = px; y = py; z = pz; }
359
+  FI void set(const XYval<T> pxy)                      { x = pxy.x; y = pxy.y; }
309
   FI void set(const XYval<T> pxy, const T pz)          { x = pxy.x; y = pxy.y; z = pz; }
360
   FI void set(const XYval<T> pxy, const T pz)          { x = pxy.x; y = pxy.y; z = pz; }
310
   FI void set(const T (&arr)[XY])                      { x = arr[0]; y = arr[1]; }
361
   FI void set(const T (&arr)[XY])                      { x = arr[0]; y = arr[1]; }
311
-  FI void set(const T (&arr)[XYZ])                     { x = arr[0]; y = arr[1]; z = arr[2]; }
312
-  FI void set(const T (&arr)[XYZE])                    { x = arr[0]; y = arr[1]; z = arr[2]; }
313
-  #if DISTINCT_AXES > XYZE
314
-    FI void set(const T (&arr)[DISTINCT_AXES])         { x = arr[0]; y = arr[1]; z = arr[2]; }
362
+  FI void set(const T (&arr)[LINEAR_AXES])             { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2]); }
363
+  #if LINEAR_AXES >= XYZ
364
+    FI void set(LINEAR_AXIS_LIST(const T px, const T py, const T pz))
365
+                                                       { LINEAR_AXIS_CODE(x = px, y = py, z = pz); }
366
+  #endif
367
+  #if LOGICAL_AXES > LINEAR_AXES
368
+    FI void set(const T (&arr)[LOGICAL_AXES])          { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2]); }
369
+    FI void set(LOGICAL_AXIS_LIST(const T, const T px, const T py, const T pz))
370
+                                                       { LINEAR_AXIS_CODE(x = px, y = py, z = pz); }
371
+    #if DISTINCT_AXES > LOGICAL_AXES
372
+      FI void set(const T (&arr)[DISTINCT_AXES])       { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2]); }
373
+    #endif
315
   #endif
374
   #endif
316
-  FI void reset()                                      { x = y = z = 0; }
317
-  FI T magnitude()                               const { return (T)sqrtf(x*x + y*y + z*z); }
375
+  FI void reset()                                      { LINEAR_AXIS_GANG(x =, y =, z =) 0; }
376
+  FI T magnitude()                               const { return (T)sqrtf(LINEAR_AXIS_GANG(x*x, + y*y, + z*z)); }
318
   FI operator T* ()                                    { return pos; }
377
   FI operator T* ()                                    { return pos; }
319
-  FI operator bool()                                   { return z || x || y; }
378
+  FI operator bool()                                   { return LINEAR_AXIS_GANG(z, || x, || y); }
320
   FI XYZval<T>          copy()                   const { XYZval<T> o = *this; return o; }
379
   FI XYZval<T>          copy()                   const { XYZval<T> o = *this; return o; }
321
-  FI XYZval<T>           ABS()                   const { return { T(_ABS(x)), T(_ABS(y)), T(_ABS(z)) }; }
322
-  FI XYZval<int16_t>   asInt()                         { return { int16_t(x), int16_t(y), int16_t(z) }; }
323
-  FI XYZval<int16_t>   asInt()                   const { return { int16_t(x), int16_t(y), int16_t(z) }; }
324
-  FI XYZval<int32_t>  asLong()                         { return { int32_t(x), int32_t(y), int32_t(z) }; }
325
-  FI XYZval<int32_t>  asLong()                   const { return { int32_t(x), int32_t(y), int32_t(z) }; }
326
-  FI XYZval<int32_t>  ROUNDL()                         { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)) }; }
327
-  FI XYZval<int32_t>  ROUNDL()                   const { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)) }; }
328
-  FI XYZval<float>   asFloat()                         { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) }; }
329
-  FI XYZval<float>   asFloat()                   const { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) }; }
330
-  FI XYZval<float> reciprocal()                  const { return {  _RECIP(x),  _RECIP(y),  _RECIP(z) }; }
380
+  FI XYZval<T>           ABS()                   const { return LINEAR_AXIS_ARRAY(T(_ABS(x)), T(_ABS(y)), T(_ABS(z))); }
381
+  FI XYZval<int16_t>   asInt()                         { return LINEAR_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z)); }
382
+  FI XYZval<int16_t>   asInt()                   const { return LINEAR_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z)); }
383
+  FI XYZval<int32_t>  asLong()                         { return LINEAR_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z)); }
384
+  FI XYZval<int32_t>  asLong()                   const { return LINEAR_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z)); }
385
+  FI XYZval<int32_t>  ROUNDL()                         { return LINEAR_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z))); }
386
+  FI XYZval<int32_t>  ROUNDL()                   const { return LINEAR_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z))); }
387
+  FI XYZval<float>   asFloat()                         { return LINEAR_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)); }
388
+  FI XYZval<float>   asFloat()                   const { return LINEAR_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)); }
389
+  FI XYZval<float> reciprocal()                  const { return LINEAR_AXIS_ARRAY(_RECIP(x),  _RECIP(y),  _RECIP(z)); }
331
   FI XYZval<float> asLogical()                   const { XYZval<float> o = asFloat(); toLogical(o); return o; }
390
   FI XYZval<float> asLogical()                   const { XYZval<float> o = asFloat(); toLogical(o); return o; }
332
   FI XYZval<float>  asNative()                   const { XYZval<float> o = asFloat(); toNative(o);  return o; }
391
   FI XYZval<float>  asNative()                   const { XYZval<float> o = asFloat(); toNative(o);  return o; }
333
   FI operator       XYval<T>&()                        { return *(XYval<T>*)this; }
392
   FI operator       XYval<T>&()                        { return *(XYval<T>*)this; }
334
   FI operator const XYval<T>&()                  const { return *(const XYval<T>*)this; }
393
   FI operator const XYval<T>&()                  const { return *(const XYval<T>*)this; }
335
-  FI operator       XYZEval<T>()                 const { return { x, y, z }; }
336
-  FI       T&   operator[](const int i)                { return pos[i]; }
337
-  FI const T&   operator[](const int i)          const { return pos[i]; }
338
-  FI XYZval<T>& operator= (const T v)                  { set(v,    v,    v   ); return *this; }
394
+  FI operator       XYZEval<T>()                 const { return LINEAR_AXIS_ARRAY(x, y, z); }
395
+  FI       T&   operator[](const int n)                { return pos[n]; }
396
+  FI const T&   operator[](const int n)          const { return pos[n]; }
397
+  FI XYZval<T>& operator= (const T v)                  { set(ARRAY_N_1(LINEAR_AXES, v)); return *this; }
339
   FI XYZval<T>& operator= (const XYval<T>   &rs)       { set(rs.x, rs.y      ); return *this; }
398
   FI XYZval<T>& operator= (const XYval<T>   &rs)       { set(rs.x, rs.y      ); return *this; }
340
-  FI XYZval<T>& operator= (const XYZEval<T> &rs)       { set(rs.x, rs.y, rs.z); return *this; }
341
-  FI XYZval<T>  operator+ (const XYval<T>   &rs) const { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y;               return ls; }
342
-  FI XYZval<T>  operator+ (const XYval<T>   &rs)       { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y;               return ls; }
343
-  FI XYZval<T>  operator- (const XYval<T>   &rs) const { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y;               return ls; }
344
-  FI XYZval<T>  operator- (const XYval<T>   &rs)       { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y;               return ls; }
345
-  FI XYZval<T>  operator* (const XYval<T>   &rs) const { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y;               return ls; }
346
-  FI XYZval<T>  operator* (const XYval<T>   &rs)       { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y;               return ls; }
347
-  FI XYZval<T>  operator/ (const XYval<T>   &rs) const { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y;               return ls; }
348
-  FI XYZval<T>  operator/ (const XYval<T>   &rs)       { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y;               return ls; }
349
-  FI XYZval<T>  operator+ (const XYZval<T>  &rs) const { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; return ls; }
350
-  FI XYZval<T>  operator+ (const XYZval<T>  &rs)       { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; return ls; }
351
-  FI XYZval<T>  operator- (const XYZval<T>  &rs) const { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; return ls; }
352
-  FI XYZval<T>  operator- (const XYZval<T>  &rs)       { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; return ls; }
353
-  FI XYZval<T>  operator* (const XYZval<T>  &rs) const { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; return ls; }
354
-  FI XYZval<T>  operator* (const XYZval<T>  &rs)       { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; return ls; }
355
-  FI XYZval<T>  operator/ (const XYZval<T>  &rs) const { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; return ls; }
356
-  FI XYZval<T>  operator/ (const XYZval<T>  &rs)       { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; return ls; }
357
-  FI XYZval<T>  operator+ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; return ls; }
358
-  FI XYZval<T>  operator+ (const XYZEval<T> &rs)       { XYZval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; return ls; }
359
-  FI XYZval<T>  operator- (const XYZEval<T> &rs) const { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; return ls; }
360
-  FI XYZval<T>  operator- (const XYZEval<T> &rs)       { XYZval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; return ls; }
361
-  FI XYZval<T>  operator* (const XYZEval<T> &rs) const { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; return ls; }
362
-  FI XYZval<T>  operator* (const XYZEval<T> &rs)       { XYZval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; return ls; }
363
-  FI XYZval<T>  operator/ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; return ls; }
364
-  FI XYZval<T>  operator/ (const XYZEval<T> &rs)       { XYZval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; return ls; }
365
-  FI XYZval<T>  operator* (const float &v)       const { XYZval<T> ls = *this; ls.x *= v;    ls.y *= v;    ls.z *= v;    return ls; }
366
-  FI XYZval<T>  operator* (const float &v)             { XYZval<T> ls = *this; ls.x *= v;    ls.y *= v;    ls.z *= v;    return ls; }
367
-  FI XYZval<T>  operator* (const int &v)         const { XYZval<T> ls = *this; ls.x *= v;    ls.y *= v;    ls.z *= v;    return ls; }
368
-  FI XYZval<T>  operator* (const int &v)               { XYZval<T> ls = *this; ls.x *= v;    ls.y *= v;    ls.z *= v;    return ls; }
369
-  FI XYZval<T>  operator/ (const float &v)       const { XYZval<T> ls = *this; ls.x /= v;    ls.y /= v;    ls.z /= v;    return ls; }
370
-  FI XYZval<T>  operator/ (const float &v)             { XYZval<T> ls = *this; ls.x /= v;    ls.y /= v;    ls.z /= v;    return ls; }
371
-  FI XYZval<T>  operator/ (const int &v)         const { XYZval<T> ls = *this; ls.x /= v;    ls.y /= v;    ls.z /= v;    return ls; }
372
-  FI XYZval<T>  operator/ (const int &v)               { XYZval<T> ls = *this; ls.x /= v;    ls.y /= v;    ls.z /= v;    return ls; }
373
-  FI XYZval<T>  operator>>(const int &v)         const { XYZval<T> ls = *this; _RS(ls.x); _RS(ls.y); _RS(ls.z); return ls; }
374
-  FI XYZval<T>  operator>>(const int &v)               { XYZval<T> ls = *this; _RS(ls.x); _RS(ls.y); _RS(ls.z); return ls; }
375
-  FI XYZval<T>  operator<<(const int &v)         const { XYZval<T> ls = *this; _LS(ls.x); _LS(ls.y); _LS(ls.z); return ls; }
376
-  FI XYZval<T>  operator<<(const int &v)               { XYZval<T> ls = *this; _LS(ls.x); _LS(ls.y); _LS(ls.z); return ls; }
377
-  FI XYZval<T>& operator+=(const XYval<T>   &rs)       { x += rs.x; y += rs.y;            return *this; }
378
-  FI XYZval<T>& operator-=(const XYval<T>   &rs)       { x -= rs.x; y -= rs.y;            return *this; }
379
-  FI XYZval<T>& operator*=(const XYval<T>   &rs)       { x *= rs.x; y *= rs.y;            return *this; }
380
-  FI XYZval<T>& operator/=(const XYval<T>   &rs)       { x /= rs.x; y /= rs.y;            return *this; }
381
-  FI XYZval<T>& operator+=(const XYZval<T>  &rs)       { x += rs.x; y += rs.y; z += rs.z; return *this; }
382
-  FI XYZval<T>& operator-=(const XYZval<T>  &rs)       { x -= rs.x; y -= rs.y; z -= rs.z; return *this; }
383
-  FI XYZval<T>& operator*=(const XYZval<T>  &rs)       { x *= rs.x; y *= rs.y; z *= rs.z; return *this; }
384
-  FI XYZval<T>& operator/=(const XYZval<T>  &rs)       { x /= rs.x; y /= rs.y; z /= rs.z; return *this; }
385
-  FI XYZval<T>& operator+=(const XYZEval<T> &rs)       { x += rs.x; y += rs.y; z += rs.z; return *this; }
386
-  FI XYZval<T>& operator-=(const XYZEval<T> &rs)       { x -= rs.x; y -= rs.y; z -= rs.z; return *this; }
387
-  FI XYZval<T>& operator*=(const XYZEval<T> &rs)       { x *= rs.x; y *= rs.y; z *= rs.z; return *this; }
388
-  FI XYZval<T>& operator/=(const XYZEval<T> &rs)       { x /= rs.x; y /= rs.y; z /= rs.z; return *this; }
389
-  FI XYZval<T>& operator*=(const float &v)             { x *= v;    y *= v;    z *= v;    return *this; }
390
-  FI XYZval<T>& operator*=(const int &v)               { x *= v;    y *= v;    z *= v;    return *this; }
391
-  FI XYZval<T>& operator>>=(const int &v)              { _RS(x);   _RS(y);   _RS(z);   return *this; }
392
-  FI XYZval<T>& operator<<=(const int &v)              { _LS(x);   _LS(y);   _LS(z);   return *this; }
393
-  FI bool       operator==(const XYZEval<T> &rs)       { return x == rs.x && y == rs.y && z == rs.z; }
399
+  FI XYZval<T>& operator= (const XYZEval<T> &rs)       { set(LINEAR_AXIS_LIST(rs.x, rs.y, rs.z)); return *this; }
400
+  FI XYZval<T>  operator+ (const XYval<T>   &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP        ); return ls; }
401
+  FI XYZval<T>  operator+ (const XYval<T>   &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP        ); return ls; }
402
+  FI XYZval<T>  operator- (const XYval<T>   &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP        ); return ls; }
403
+  FI XYZval<T>  operator- (const XYval<T>   &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP        ); return ls; }
404
+  FI XYZval<T>  operator* (const XYval<T>   &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP        ); return ls; }
405
+  FI XYZval<T>  operator* (const XYval<T>   &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP        ); return ls; }
406
+  FI XYZval<T>  operator/ (const XYval<T>   &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP        ); return ls; }
407
+  FI XYZval<T>  operator/ (const XYval<T>   &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP        ); return ls; }
408
+  FI XYZval<T>  operator+ (const XYZval<T>  &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z); return ls; }
409
+  FI XYZval<T>  operator+ (const XYZval<T>  &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z); return ls; }
410
+  FI XYZval<T>  operator- (const XYZval<T>  &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z); return ls; }
411
+  FI XYZval<T>  operator- (const XYZval<T>  &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z); return ls; }
412
+  FI XYZval<T>  operator* (const XYZval<T>  &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z); return ls; }
413
+  FI XYZval<T>  operator* (const XYZval<T>  &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z); return ls; }
414
+  FI XYZval<T>  operator/ (const XYZval<T>  &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z); return ls; }
415
+  FI XYZval<T>  operator/ (const XYZval<T>  &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z); return ls; }
416
+  FI XYZval<T>  operator+ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z); return ls; }
417
+  FI XYZval<T>  operator+ (const XYZEval<T> &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z); return ls; }
418
+  FI XYZval<T>  operator- (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z); return ls; }
419
+  FI XYZval<T>  operator- (const XYZEval<T> &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z); return ls; }
420
+  FI XYZval<T>  operator* (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z); return ls; }
421
+  FI XYZval<T>  operator* (const XYZEval<T> &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z); return ls; }
422
+  FI XYZval<T>  operator/ (const XYZEval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z); return ls; }
423
+  FI XYZval<T>  operator/ (const XYZEval<T> &rs)       { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z); return ls; }
424
+  FI XYZval<T>  operator* (const float &v)       const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v,    ls.y *= v,    ls.z *= v   ); return ls; }
425
+  FI XYZval<T>  operator* (const float &v)             { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v,    ls.y *= v,    ls.z *= v   ); return ls; }
426
+  FI XYZval<T>  operator* (const int &v)         const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v,    ls.y *= v,    ls.z *= v   ); return ls; }
427
+  FI XYZval<T>  operator* (const int &v)               { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= v,    ls.y *= v,    ls.z *= v   ); return ls; }
428
+  FI XYZval<T>  operator/ (const float &v)       const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v,    ls.y /= v,    ls.z /= v   ); return ls; }
429
+  FI XYZval<T>  operator/ (const float &v)             { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v,    ls.y /= v,    ls.z /= v   ); return ls; }
430
+  FI XYZval<T>  operator/ (const int &v)         const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v,    ls.y /= v,    ls.z /= v   ); return ls; }
431
+  FI XYZval<T>  operator/ (const int &v)               { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= v,    ls.y /= v,    ls.z /= v   ); return ls; }
432
+  FI XYZval<T>  operator>>(const int &v)         const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_RS(ls.x),    _RS(ls.y),    _RS(ls.z)   ); return ls; }
433
+  FI XYZval<T>  operator>>(const int &v)               { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_RS(ls.x),    _RS(ls.y),    _RS(ls.z)   ); return ls; }
434
+  FI XYZval<T>  operator<<(const int &v)         const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_LS(ls.x),    _LS(ls.y),    _LS(ls.z)   ); return ls; }
435
+  FI XYZval<T>  operator<<(const int &v)               { XYZval<T> ls = *this; LINEAR_AXIS_CODE(_LS(ls.x),    _LS(ls.y),    _LS(ls.z)   ); return ls; }
436
+  FI XYZval<T>& operator+=(const XYval<T>   &rs)       { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, NOOP      ); return *this; }
437
+  FI XYZval<T>& operator-=(const XYval<T>   &rs)       { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP      ); return *this; }
438
+  FI XYZval<T>& operator*=(const XYval<T>   &rs)       { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, NOOP      ); return *this; }
439
+  FI XYZval<T>& operator/=(const XYval<T>   &rs)       { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, NOOP      ); return *this; }
440
+  FI XYZval<T>& operator+=(const XYZval<T>  &rs)       { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z ); return *this; }
441
+  FI XYZval<T>& operator-=(const XYZval<T>  &rs)       { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z ); return *this; }
442
+  FI XYZval<T>& operator*=(const XYZval<T>  &rs)       { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z ); return *this; }
443
+  FI XYZval<T>& operator/=(const XYZval<T>  &rs)       { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z ); return *this; }
444
+  FI XYZval<T>& operator+=(const XYZEval<T> &rs)       { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z ); return *this; }
445
+  FI XYZval<T>& operator-=(const XYZEval<T> &rs)       { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z ); return *this; }
446
+  FI XYZval<T>& operator*=(const XYZEval<T> &rs)       { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z ); return *this; }
447
+  FI XYZval<T>& operator/=(const XYZEval<T> &rs)       { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z ); return *this; }
448
+  FI XYZval<T>& operator*=(const float &v)             { LINEAR_AXIS_CODE(x *= v,    y *= v,    z *= v    ); return *this; }
449
+  FI XYZval<T>& operator*=(const int &v)               { LINEAR_AXIS_CODE(x *= v,    y *= v,    z *= v    ); return *this; }
450
+  FI XYZval<T>& operator>>=(const int &v)              { LINEAR_AXIS_CODE(_RS(x),    _RS(y),    _RS(z)    ); return *this; }
451
+  FI XYZval<T>& operator<<=(const int &v)              { LINEAR_AXIS_CODE(_LS(x),    _LS(y),    _LS(z)    ); return *this; }
452
+  FI bool       operator==(const XYZEval<T> &rs)       { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z); }
453
+  FI bool       operator==(const XYZEval<T> &rs) const { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z); }
394
   FI bool       operator!=(const XYZEval<T> &rs)       { return !operator==(rs); }
454
   FI bool       operator!=(const XYZEval<T> &rs)       { return !operator==(rs); }
395
-  FI bool       operator==(const XYZEval<T> &rs) const { return x == rs.x && y == rs.y && z == rs.z; }
396
   FI bool       operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
455
   FI bool       operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
397
-  FI XYZval<T>       operator-()                       { XYZval<T> o = *this; o.x = -x; o.y = -y; o.z = -z; return o; }
398
-  FI const XYZval<T> operator-()                 const { XYZval<T> o = *this; o.x = -x; o.y = -y; o.z = -z; return o; }
456
+  FI XYZval<T>       operator-()                       { XYZval<T> o = *this; LINEAR_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z); return o; }
457
+  FI const XYZval<T> operator-()                 const { XYZval<T> o = *this; LINEAR_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z); return o; }
399
 };
458
 };
400
 
459
 
401
 //
460
 //
402
-// XYZE coordinates, counters, etc.
461
+// Logical Axes coordinates, counters, etc.
403
 //
462
 //
404
 template<typename T>
463
 template<typename T>
405
 struct XYZEval {
464
 struct XYZEval {
406
   union {
465
   union {
407
-    struct{ T x, y, z, e; };
408
-    struct{ T a, b, c; };
409
-    T pos[4];
466
+    struct{ T LOGICAL_AXIS_LIST(e, x, y, z); };
467
+    struct{ T LINEAR_AXIS_LIST(a, b, c); };
468
+    T pos[LOGICAL_AXES];
410
   };
469
   };
411
-  FI void reset()                                             { x = y = z = e = 0; }
412
-  FI T magnitude()                                      const { return (T)sqrtf(x*x + y*y + z*z + e*e); }
470
+  FI void reset()                                             { LOGICAL_AXIS_GANG(e =, x =, y =, z =) 0; }
471
+  FI T magnitude()                                      const { return (T)sqrtf(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z)); }
413
   FI operator T* ()                                           { return pos; }
472
   FI operator T* ()                                           { return pos; }
414
-  FI operator bool()                                          { return e || z || x || y; }
415
-  FI void set(const T px)                                     { x = px;                                        }
416
-  FI void set(const T px, const T py)                         { x = px;     y = py;                            }
417
-  FI void set(const T px, const T py, const T pz)             { x = px;     y = py;     z = pz;                }
418
-  FI void set(const T px, const T py, const T pz, const T pe) { x = px;     y = py;     z = pz;     e = pe;    }
419
-  FI void set(const XYval<T> pxy)                             { x = pxy.x;  y = pxy.y;                         }
420
-  FI void set(const XYval<T> pxy, const T pz)                 { x = pxy.x;  y = pxy.y;  z = pz;                }
421
-  FI void set(const XYZval<T> pxyz)                           { x = pxyz.x; y = pxyz.y; z = pxyz.z;            }
422
-  FI void set(const XYval<T> pxy, const T pz, const T pe)     { x = pxy.x;  y = pxy.y;  z = pz;     e = pe;    }
423
-  FI void set(const XYval<T> pxy, const XYval<T> pze)         { x = pxy.x;  y = pxy.y;  z = pze.z;  e = pze.e; }
424
-  FI void set(const XYZval<T> pxyz, const T pe)               { x = pxyz.x; y = pxyz.y; z = pxyz.z; e = pe;    }
425
-  FI void set(const T (&arr)[XY])                             { x = arr[0]; y = arr[1]; }
426
-  FI void set(const T (&arr)[XYZ])                            { x = arr[0]; y = arr[1]; z = arr[2]; }
427
-  FI void set(const T (&arr)[XYZE])                           { x = arr[0]; y = arr[1]; z = arr[2]; e = arr[3]; }
428
-  #if DISTINCT_AXES > XYZE
429
-    FI void set(const T (&arr)[DISTINCT_AXES])                { x = arr[0]; y = arr[1]; z = arr[2]; e = arr[3]; }
473
+  FI operator bool()                                          { return false LOGICAL_AXIS_GANG(|| e, || x, || y, || z); }
474
+  FI void set(const T px)                                     { x = px;               }
475
+  FI void set(const T px, const T py)                         { x = px;    y = py;    }
476
+  FI void set(const XYval<T> pxy)                             { x = pxy.x; y = pxy.y; }
477
+  FI void set(const XYZval<T> pxyz)                           { set(LINEAR_AXIS_LIST(pxyz.x, pxyz.y, pxyz.z)); }
478
+  #if LINEAR_AXES >= XYZ
479
+    FI void set(LINEAR_AXIS_LIST(const T px, const T py, const T pz)) {
480
+      LINEAR_AXIS_CODE(x = px, y = py, z = pz);
481
+    }
430
   #endif
482
   #endif
431
-  FI XYZEval<T>          copy()                         const { return *this; }
432
-  FI XYZEval<T>           ABS()                         const { return { T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(e)) }; }
433
-  FI XYZEval<int16_t>   asInt()                               { return { int16_t(x), int16_t(y), int16_t(z), int16_t(e) }; }
434
-  FI XYZEval<int16_t>   asInt()                         const { return { int16_t(x), int16_t(y), int16_t(z), int16_t(e) }; }
435
-  FI XYZEval<int32_t>  asLong()                               { return { int32_t(x), int32_t(y), int32_t(z), int32_t(e) }; }
436
-  FI XYZEval<int32_t>  asLong()                         const { return { int32_t(x), int32_t(y), int32_t(z), int32_t(e) }; }
437
-  FI XYZEval<int32_t>  ROUNDL()                               { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(e)) }; }
438
-  FI XYZEval<int32_t>  ROUNDL()                         const { return { int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(e)) }; }
439
-  FI XYZEval<float>   asFloat()                               { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(e) }; }
440
-  FI XYZEval<float>   asFloat()                         const { return { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(e) }; }
441
-  FI XYZEval<float> reciprocal()                        const { return {  _RECIP(x),  _RECIP(y),  _RECIP(z),  _RECIP(e) }; }
483
+  #if LOGICAL_AXES > LINEAR_AXES
484
+    FI void set(LOGICAL_AXIS_LIST(const T pe, const T px, const T py, const T pz)) {
485
+      LOGICAL_AXIS_CODE(e = pe, x = px, y = py, z = pz);
486
+    }
487
+    FI void set(const XYval<T> pxy, const T pe)               { set(pxy); e = pe; }
488
+    FI void set(const XYZval<T> pxyz, const T pe)             { set(pxyz); e = pe; }
489
+  #endif
490
+  FI XYZEval<T>          copy()                         const { XYZEval<T> o = *this; return o; }
491
+  FI XYZEval<T>           ABS()                         const { return LOGICAL_AXIS_ARRAY(T(_ABS(e)), T(_ABS(x)), T(_ABS(y)), T(_ABS(z))); }
492
+  FI XYZEval<int16_t>   asInt()                               { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z)); }
493
+  FI XYZEval<int16_t>   asInt()                         const { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z)); }
494
+  FI XYZEval<int32_t>  asLong()                               { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z)); }
495
+  FI XYZEval<int32_t>  asLong()                         const { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z)); }
496
+  FI XYZEval<int32_t>  ROUNDL()                               { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z))); }
497
+  FI XYZEval<int32_t>  ROUNDL()                         const { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z))); }
498
+  FI XYZEval<float>   asFloat()                               { return LOGICAL_AXIS_ARRAY(static_cast<float>(e), static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)); }
499
+  FI XYZEval<float>   asFloat()                         const { return LOGICAL_AXIS_ARRAY(static_cast<float>(e), static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)); }
500
+  FI XYZEval<float> reciprocal()                        const { return LOGICAL_AXIS_ARRAY(_RECIP(e),  _RECIP(x),  _RECIP(y),  _RECIP(z)); }
442
   FI XYZEval<float> asLogical()                         const { XYZEval<float> o = asFloat(); toLogical(o); return o; }
501
   FI XYZEval<float> asLogical()                         const { XYZEval<float> o = asFloat(); toLogical(o); return o; }
443
   FI XYZEval<float>  asNative()                         const { XYZEval<float> o = asFloat(); toNative(o);  return o; }
502
   FI XYZEval<float>  asNative()                         const { XYZEval<float> o = asFloat(); toNative(o);  return o; }
444
   FI operator       XYval<T>&()                               { return *(XYval<T>*)this; }
503
   FI operator       XYval<T>&()                               { return *(XYval<T>*)this; }
445
   FI operator const XYval<T>&()                         const { return *(const XYval<T>*)this; }
504
   FI operator const XYval<T>&()                         const { return *(const XYval<T>*)this; }
446
   FI operator       XYZval<T>&()                              { return *(XYZval<T>*)this; }
505
   FI operator       XYZval<T>&()                              { return *(XYZval<T>*)this; }
447
   FI operator const XYZval<T>&()                        const { return *(const XYZval<T>*)this; }
506
   FI operator const XYZval<T>&()                        const { return *(const XYZval<T>*)this; }
448
-  FI       T&    operator[](const int i)                      { return pos[i]; }
449
-  FI const T&    operator[](const int i)                const { return pos[i]; }
450
-  FI XYZEval<T>& operator= (const T v)                        { set(v, v, v, v); return *this; }
507
+  FI       T&    operator[](const int n)                      { return pos[n]; }
508
+  FI const T&    operator[](const int n)                const { return pos[n]; }
509
+  FI XYZEval<T>& operator= (const T v)                        { set(LIST_N_1(LINEAR_AXES, v)); return *this; }
451
   FI XYZEval<T>& operator= (const XYval<T>   &rs)             { set(rs.x, rs.y); return *this; }
510
   FI XYZEval<T>& operator= (const XYval<T>   &rs)             { set(rs.x, rs.y); return *this; }
452
-  FI XYZEval<T>& operator= (const XYZval<T>  &rs)             { set(rs.x, rs.y, rs.z); return *this; }
453
-  FI XYZEval<T>  operator+ (const XYval<T>   &rs)       const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y;                             return ls; }
454
-  FI XYZEval<T>  operator+ (const XYval<T>   &rs)             { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y;                             return ls; }
455
-  FI XYZEval<T>  operator- (const XYval<T>   &rs)       const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y;                             return ls; }
456
-  FI XYZEval<T>  operator- (const XYval<T>   &rs)             { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y;                             return ls; }
457
-  FI XYZEval<T>  operator* (const XYval<T>   &rs)       const { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y;                             return ls; }
458
-  FI XYZEval<T>  operator* (const XYval<T>   &rs)             { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y;                             return ls; }
459
-  FI XYZEval<T>  operator/ (const XYval<T>   &rs)       const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y;                             return ls; }
460
-  FI XYZEval<T>  operator/ (const XYval<T>   &rs)             { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y;                             return ls; }
461
-  FI XYZEval<T>  operator+ (const XYZval<T>  &rs)       const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z;               return ls; }
462
-  FI XYZEval<T>  operator+ (const XYZval<T>  &rs)             { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z;               return ls; }
463
-  FI XYZEval<T>  operator- (const XYZval<T>  &rs)       const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z;               return ls; }
464
-  FI XYZEval<T>  operator- (const XYZval<T>  &rs)             { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z;               return ls; }
465
-  FI XYZEval<T>  operator* (const XYZval<T>  &rs)       const { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z;               return ls; }
466
-  FI XYZEval<T>  operator* (const XYZval<T>  &rs)             { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z;               return ls; }
467
-  FI XYZEval<T>  operator/ (const XYZval<T>  &rs)       const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z;               return ls; }
468
-  FI XYZEval<T>  operator/ (const XYZval<T>  &rs)             { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z;               return ls; }
469
-  FI XYZEval<T>  operator+ (const XYZEval<T> &rs)       const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; ls.e += rs.e; return ls; }
470
-  FI XYZEval<T>  operator+ (const XYZEval<T> &rs)             { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; ls.z += rs.z; ls.e += rs.e; return ls; }
471
-  FI XYZEval<T>  operator- (const XYZEval<T> &rs)       const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; ls.e -= rs.e; return ls; }
472
-  FI XYZEval<T>  operator- (const XYZEval<T> &rs)             { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; ls.z -= rs.z; ls.e -= rs.e; return ls; }
473
-  FI XYZEval<T>  operator* (const XYZEval<T> &rs)       const { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; ls.e *= rs.e; return ls; }
474
-  FI XYZEval<T>  operator* (const XYZEval<T> &rs)             { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; ls.z *= rs.z; ls.e *= rs.e; return ls; }
475
-  FI XYZEval<T>  operator/ (const XYZEval<T> &rs)       const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; ls.e /= rs.e; return ls; }
476
-  FI XYZEval<T>  operator/ (const XYZEval<T> &rs)             { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; ls.z /= rs.z; ls.e /= rs.e; return ls; }
477
-  FI XYZEval<T>  operator* (const float &v)             const { XYZEval<T> ls = *this; ls.x *= v;    ls.y *= v;    ls.z *= v;    ls.e *= v;    return ls; }
478
-  FI XYZEval<T>  operator* (const float &v)                   { XYZEval<T> ls = *this; ls.x *= v;    ls.y *= v;    ls.z *= v;    ls.e *= v;    return ls; }
479
-  FI XYZEval<T>  operator* (const int &v)               const { XYZEval<T> ls = *this; ls.x *= v;    ls.y *= v;    ls.z *= v;    ls.e *= v;    return ls; }
480
-  FI XYZEval<T>  operator* (const int &v)                     { XYZEval<T> ls = *this; ls.x *= v;    ls.y *= v;    ls.z *= v;    ls.e *= v;    return ls; }
481
-  FI XYZEval<T>  operator/ (const float &v)             const { XYZEval<T> ls = *this; ls.x /= v;    ls.y /= v;    ls.z /= v;    ls.e /= v;    return ls; }
482
-  FI XYZEval<T>  operator/ (const float &v)                   { XYZEval<T> ls = *this; ls.x /= v;    ls.y /= v;    ls.z /= v;    ls.e /= v;    return ls; }
483
-  FI XYZEval<T>  operator/ (const int &v)               const { XYZEval<T> ls = *this; ls.x /= v;    ls.y /= v;    ls.z /= v;    ls.e /= v;    return ls; }
484
-  FI XYZEval<T>  operator/ (const int &v)                     { XYZEval<T> ls = *this; ls.x /= v;    ls.y /= v;    ls.z /= v;    ls.e /= v;    return ls; }
485
-  FI XYZEval<T>  operator>>(const int &v)               const { XYZEval<T> ls = *this; _RS(ls.x);    _RS(ls.y);    _RS(ls.z);    _RS(ls.e);    return ls; }
486
-  FI XYZEval<T>  operator>>(const int &v)                     { XYZEval<T> ls = *this; _RS(ls.x);    _RS(ls.y);    _RS(ls.z);    _RS(ls.e);    return ls; }
487
-  FI XYZEval<T>  operator<<(const int &v)               const { XYZEval<T> ls = *this; _LS(ls.x);    _LS(ls.y);    _LS(ls.z);    _LS(ls.e);    return ls; }
488
-  FI XYZEval<T>  operator<<(const int &v)                     { XYZEval<T> ls = *this; _LS(ls.x);    _LS(ls.y);    _LS(ls.z);    _LS(ls.e);    return ls; }
489
-  FI XYZEval<T>& operator+=(const XYval<T>   &rs)             { x += rs.x; y += rs.y;                       return *this; }
490
-  FI XYZEval<T>& operator-=(const XYval<T>   &rs)             { x -= rs.x; y -= rs.y;                       return *this; }
491
-  FI XYZEval<T>& operator*=(const XYval<T>   &rs)             { x *= rs.x; y *= rs.y;                       return *this; }
492
-  FI XYZEval<T>& operator/=(const XYval<T>   &rs)             { x /= rs.x; y /= rs.y;                       return *this; }
493
-  FI XYZEval<T>& operator+=(const XYZval<T>  &rs)             { x += rs.x; y += rs.y; z += rs.z;            return *this; }
494
-  FI XYZEval<T>& operator-=(const XYZval<T>  &rs)             { x -= rs.x; y -= rs.y; z -= rs.z;            return *this; }
495
-  FI XYZEval<T>& operator*=(const XYZval<T>  &rs)             { x *= rs.x; y *= rs.y; z *= rs.z;            return *this; }
496
-  FI XYZEval<T>& operator/=(const XYZval<T>  &rs)             { x /= rs.x; y /= rs.y; z /= rs.z;            return *this; }
497
-  FI XYZEval<T>& operator+=(const XYZEval<T> &rs)             { x += rs.x; y += rs.y; z += rs.z; e += rs.e; return *this; }
498
-  FI XYZEval<T>& operator-=(const XYZEval<T> &rs)             { x -= rs.x; y -= rs.y; z -= rs.z; e -= rs.e; return *this; }
499
-  FI XYZEval<T>& operator*=(const XYZEval<T> &rs)             { x *= rs.x; y *= rs.y; z *= rs.z; e *= rs.e; return *this; }
500
-  FI XYZEval<T>& operator/=(const XYZEval<T> &rs)             { x /= rs.x; y /= rs.y; z /= rs.z; e /= rs.e; return *this; }
501
-  FI XYZEval<T>& operator*=(const T &v)                       { x *= v;    y *= v;    z *= v;    e *= v;    return *this; }
502
-  FI XYZEval<T>& operator>>=(const int &v)                    { _RS(x);    _RS(y);    _RS(z);    _RS(e);    return *this; }
503
-  FI XYZEval<T>& operator<<=(const int &v)                    { _LS(x);    _LS(y);    _LS(z);    _LS(e);    return *this; }
504
-  FI bool        operator==(const XYZval<T>  &rs)             { return x == rs.x && y == rs.y && z == rs.z; }
511
+  FI XYZEval<T>& operator= (const XYZval<T>  &rs)             { set(LINEAR_AXIS_LIST(rs.x, rs.y, rs.z)); return *this; }
512
+  FI XYZEval<T>  operator+ (const XYval<T>   &rs)       const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
513
+  FI XYZEval<T>  operator+ (const XYval<T>   &rs)             { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
514
+  FI XYZEval<T>  operator- (const XYval<T>   &rs)       const { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
515
+  FI XYZEval<T>  operator- (const XYval<T>   &rs)             { XYZEval<T> ls = *this; ls.x -= rs.x; ls.y -= rs.y; return ls; }
516
+  FI XYZEval<T>  operator* (const XYval<T>   &rs)       const { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
517
+  FI XYZEval<T>  operator* (const XYval<T>   &rs)             { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
518
+  FI XYZEval<T>  operator/ (const XYval<T>   &rs)       const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
519
+  FI XYZEval<T>  operator/ (const XYval<T>   &rs)             { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
520
+  FI XYZEval<T>  operator+ (const XYZval<T>  &rs)       const { XYZval<T>  ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z); return ls; }
521
+  FI XYZEval<T>  operator+ (const XYZval<T>  &rs)             { XYZval<T>  ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z); return ls; }
522
+  FI XYZEval<T>  operator- (const XYZval<T>  &rs)       const { XYZval<T>  ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z); return ls; }
523
+  FI XYZEval<T>  operator- (const XYZval<T>  &rs)             { XYZval<T>  ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z); return ls; }
524
+  FI XYZEval<T>  operator* (const XYZval<T>  &rs)       const { XYZval<T>  ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z); return ls; }
525
+  FI XYZEval<T>  operator* (const XYZval<T>  &rs)             { XYZval<T>  ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z); return ls; }
526
+  FI XYZEval<T>  operator/ (const XYZval<T>  &rs)       const { XYZval<T>  ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z); return ls; }
527
+  FI XYZEval<T>  operator/ (const XYZval<T>  &rs)             { XYZval<T>  ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z); return ls; }
528
+  FI XYZEval<T>  operator+ (const XYZEval<T> &rs)       const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z ); return ls; }
529
+  FI XYZEval<T>  operator+ (const XYZEval<T> &rs)             { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z ); return ls; }
530
+  FI XYZEval<T>  operator- (const XYZEval<T> &rs)       const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z ); return ls; }
531
+  FI XYZEval<T>  operator- (const XYZEval<T> &rs)             { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z ); return ls; }
532
+  FI XYZEval<T>  operator* (const XYZEval<T> &rs)       const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z ); return ls; }
533
+  FI XYZEval<T>  operator* (const XYZEval<T> &rs)             { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z ); return ls; }
534
+  FI XYZEval<T>  operator/ (const XYZEval<T> &rs)       const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z ); return ls; }
535
+  FI XYZEval<T>  operator/ (const XYZEval<T> &rs)             { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z ); return ls; }
536
+  FI XYZEval<T>  operator* (const float &v)             const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v,    ls.x *= v,    ls.y *= v,    ls.z *= v    ); return ls; }
537
+  FI XYZEval<T>  operator* (const float &v)                   { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v,    ls.x *= v,    ls.y *= v,    ls.z *= v    ); return ls; }
538
+  FI XYZEval<T>  operator* (const int &v)               const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v,    ls.x *= v,    ls.y *= v,    ls.z *= v    ); return ls; }
539
+  FI XYZEval<T>  operator* (const int &v)                     { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e *= v,    ls.x *= v,    ls.y *= v,    ls.z *= v    ); return ls; }
540
+  FI XYZEval<T>  operator/ (const float &v)             const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v,    ls.x /= v,    ls.y /= v,    ls.z /= v    ); return ls; }
541
+  FI XYZEval<T>  operator/ (const float &v)                   { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v,    ls.x /= v,    ls.y /= v,    ls.z /= v    ); return ls; }
542
+  FI XYZEval<T>  operator/ (const int &v)               const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v,    ls.x /= v,    ls.y /= v,    ls.z /= v    ); return ls; }
543
+  FI XYZEval<T>  operator/ (const int &v)                     { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(ls.e /= v,    ls.x /= v,    ls.y /= v,    ls.z /= v    ); return ls; }
544
+  FI XYZEval<T>  operator>>(const int &v)               const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e),    _RS(ls.x),    _RS(ls.y),    _RS(ls.z)    ); return ls; }
545
+  FI XYZEval<T>  operator>>(const int &v)                     { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e),    _RS(ls.x),    _RS(ls.y),    _RS(ls.z)    ); return ls; }
546
+  FI XYZEval<T>  operator<<(const int &v)               const { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e),    _LS(ls.x),    _LS(ls.y),    _LS(ls.z)    ); return ls; }
547
+  FI XYZEval<T>  operator<<(const int &v)                     { XYZEval<T> ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e),    _LS(ls.x),    _LS(ls.y),    _LS(ls.z)    ); return ls; }
548
+  FI XYZEval<T>& operator+=(const XYval<T>   &rs)             { x += rs.x; y += rs.y; return *this; }
549
+  FI XYZEval<T>& operator-=(const XYval<T>   &rs)             { x -= rs.x; y -= rs.y; return *this; }
550
+  FI XYZEval<T>& operator*=(const XYval<T>   &rs)             { x *= rs.x; y *= rs.y; return *this; }
551
+  FI XYZEval<T>& operator/=(const XYval<T>   &rs)             { x /= rs.x; y /= rs.y; return *this; }
552
+  FI XYZEval<T>& operator+=(const XYZval<T>  &rs)             { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z); return *this; }
553
+  FI XYZEval<T>& operator-=(const XYZval<T>  &rs)             { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z); return *this; }
554
+  FI XYZEval<T>& operator*=(const XYZval<T>  &rs)             { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z); return *this; }
555
+  FI XYZEval<T>& operator/=(const XYZval<T>  &rs)             { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z); return *this; }
556
+  FI XYZEval<T>& operator+=(const XYZEval<T> &rs)             { LOGICAL_AXIS_CODE(e += rs.e, x += rs.x, y += rs.y, z += rs.z); return *this; }
557
+  FI XYZEval<T>& operator-=(const XYZEval<T> &rs)             { LOGICAL_AXIS_CODE(e -= rs.e, x -= rs.x, y -= rs.y, z -= rs.z); return *this; }
558
+  FI XYZEval<T>& operator*=(const XYZEval<T> &rs)             { LOGICAL_AXIS_CODE(e *= rs.e, x *= rs.x, y *= rs.y, z *= rs.z); return *this; }
559
+  FI XYZEval<T>& operator/=(const XYZEval<T> &rs)             { LOGICAL_AXIS_CODE(e /= rs.e, x /= rs.x, y /= rs.y, z /= rs.z); return *this; }
560
+  FI XYZEval<T>& operator*=(const T &v)                       { LOGICAL_AXIS_CODE(e *= v,    x *= v,    y *= v,    z *= v);    return *this; }
561
+  FI XYZEval<T>& operator>>=(const int &v)                    { LOGICAL_AXIS_CODE(_RS(e),    _RS(x),    _RS(y),    _RS(z));    return *this; }
562
+  FI XYZEval<T>& operator<<=(const int &v)                    { LOGICAL_AXIS_CODE(_LS(e),    _LS(x),    _LS(y),    _LS(z));    return *this; }
563
+  FI bool        operator==(const XYZval<T>  &rs)             { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z); }
564
+  FI bool        operator==(const XYZval<T>  &rs)       const { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z); }
505
   FI bool        operator!=(const XYZval<T>  &rs)             { return !operator==(rs); }
565
   FI bool        operator!=(const XYZval<T>  &rs)             { return !operator==(rs); }
506
-  FI bool        operator==(const XYZval<T>  &rs)       const { return x == rs.x && y == rs.y && z == rs.z; }
507
   FI bool        operator!=(const XYZval<T>  &rs)       const { return !operator==(rs); }
566
   FI bool        operator!=(const XYZval<T>  &rs)       const { return !operator==(rs); }
508
-  FI       XYZEval<T> operator-()                             { return { -x, -y, -z, -e }; }
509
-  FI const XYZEval<T> operator-()                       const { return { -x, -y, -z, -e }; }
567
+  FI       XYZEval<T> operator-()                             { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z); }
568
+  FI const XYZEval<T> operator-()                       const { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z); }
510
 };
569
 };
511
 
570
 
512
 #undef _RECIP
571
 #undef _RECIP
514
 #undef _LS
573
 #undef _LS
515
 #undef _RS
574
 #undef _RS
516
 #undef FI
575
 #undef FI
517
-
518
-const xyze_char_t axis_codes { 'X', 'Y', 'Z', 'E' };
519
-#define AXIS_CHAR(A) ((char)('X' + A))

+ 8
- 0
Marlin/src/core/utility.h 查看文件

76
 // Converts from an uint8_t in the range of 0-255 to an uint8_t
76
 // Converts from an uint8_t in the range of 0-255 to an uint8_t
77
 // in the range 0-100 while avoiding rounding artifacts
77
 // in the range 0-100 while avoiding rounding artifacts
78
 constexpr uint8_t ui8_to_percent(const uint8_t i) { return (int(i) * 100 + 127) / 255; }
78
 constexpr uint8_t ui8_to_percent(const uint8_t i) { return (int(i) * 100 + 127) / 255; }
79
+
80
+const xyze_char_t axis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z');
81
+
82
+#if LINEAR_AXES <= XYZ
83
+  #define AXIS_CHAR(A) ((char)('X' + A))
84
+#else
85
+  #define AXIS_CHAR(A) axis_codes[A]
86
+#endif

+ 17
- 26
Marlin/src/feature/encoder_i2c.cpp 查看文件

327
 }
327
 }
328
 
328
 
329
 bool I2CPositionEncoder::test_axis() {
329
 bool I2CPositionEncoder::test_axis() {
330
-  //only works on XYZ cartesian machines for the time being
330
+  // Only works on XYZ Cartesian machines for the time being
331
   if (!(encoderAxis == X_AXIS || encoderAxis == Y_AXIS || encoderAxis == Z_AXIS)) return false;
331
   if (!(encoderAxis == X_AXIS || encoderAxis == Y_AXIS || encoderAxis == Z_AXIS)) return false;
332
 
332
 
333
   const float startPosition = soft_endstop.min[encoderAxis] + 10,
333
   const float startPosition = soft_endstop.min[encoderAxis] + 10,
345
   endCoord[encoderAxis] = endPosition;
345
   endCoord[encoderAxis] = endPosition;
346
 
346
 
347
   planner.synchronize();
347
   planner.synchronize();
348
-  startCoord.e = planner.get_axis_position_mm(E_AXIS);
349
-  planner.buffer_line(startCoord, fr_mm_s, 0);
350
-  planner.synchronize();
348
+
349
+  #if HAS_EXTRUDERS
350
+    startCoord.e = planner.get_axis_position_mm(E_AXIS);
351
+    planner.buffer_line(startCoord, fr_mm_s, 0);
352
+    planner.synchronize();
353
+  #endif
351
 
354
 
352
   // if the module isn't currently trusted, wait until it is (or until it should be if things are working)
355
   // if the module isn't currently trusted, wait until it is (or until it should be if things are working)
353
   if (!trusted) {
356
   if (!trusted) {
357
   }
360
   }
358
 
361
 
359
   if (trusted) { // if trusted, commence test
362
   if (trusted) { // if trusted, commence test
360
-    endCoord.e = planner.get_axis_position_mm(E_AXIS);
363
+    TERN_(HAS_EXTRUDERS, endCoord.e = planner.get_axis_position_mm(E_AXIS));
361
     planner.buffer_line(endCoord, fr_mm_s, 0);
364
     planner.buffer_line(endCoord, fr_mm_s, 0);
362
     planner.synchronize();
365
     planner.synchronize();
363
   }
366
   }
402
   planner.synchronize();
405
   planner.synchronize();
403
 
406
 
404
   LOOP_L_N(i, iter) {
407
   LOOP_L_N(i, iter) {
405
-    startCoord.e = planner.get_axis_position_mm(E_AXIS);
408
+    TERN_(HAS_EXTRUDERS, startCoord.e = planner.get_axis_position_mm(E_AXIS));
406
     planner.buffer_line(startCoord, fr_mm_s, 0);
409
     planner.buffer_line(startCoord, fr_mm_s, 0);
407
     planner.synchronize();
410
     planner.synchronize();
408
 
411
 
411
 
414
 
412
     //do_blocking_move_to(endCoord);
415
     //do_blocking_move_to(endCoord);
413
 
416
 
414
-    endCoord.e = planner.get_axis_position_mm(E_AXIS);
417
+    TERN_(HAS_EXTRUDERS, endCoord.e = planner.get_axis_position_mm(E_AXIS));
415
     planner.buffer_line(endCoord, fr_mm_s, 0);
418
     planner.buffer_line(endCoord, fr_mm_s, 0);
416
     planner.synchronize();
419
     planner.synchronize();
417
 
420
 
497
 
500
 
498
     encoders[i].set_active(encoders[i].passes_test(true));
501
     encoders[i].set_active(encoders[i].passes_test(true));
499
 
502
 
500
-    #if I2CPE_ENC_1_AXIS == E_AXIS
501
-      encoders[i].set_homed();
502
-    #endif
503
+    TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_1_AXIS == E_AXIS) encoders[i].set_homed());
503
   #endif
504
   #endif
504
 
505
 
505
   #if I2CPE_ENCODER_CNT > 1
506
   #if I2CPE_ENCODER_CNT > 1
528
 
529
 
529
     encoders[i].set_active(encoders[i].passes_test(true));
530
     encoders[i].set_active(encoders[i].passes_test(true));
530
 
531
 
531
-    #if I2CPE_ENC_2_AXIS == E_AXIS
532
-      encoders[i].set_homed();
533
-    #endif
532
+    TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_2_AXIS == E_AXIS) encoders[i].set_homed());
534
   #endif
533
   #endif
535
 
534
 
536
   #if I2CPE_ENCODER_CNT > 2
535
   #if I2CPE_ENCODER_CNT > 2
557
       encoders[i].set_ec_threshold(I2CPE_ENC_3_EC_THRESH);
556
       encoders[i].set_ec_threshold(I2CPE_ENC_3_EC_THRESH);
558
     #endif
557
     #endif
559
 
558
 
560
-  encoders[i].set_active(encoders[i].passes_test(true));
559
+    encoders[i].set_active(encoders[i].passes_test(true));
561
 
560
 
562
-    #if I2CPE_ENC_3_AXIS == E_AXIS
563
-      encoders[i].set_homed();
564
-    #endif
561
+    TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_3_AXIS == E_AXIS) encoders[i].set_homed());
565
   #endif
562
   #endif
566
 
563
 
567
   #if I2CPE_ENCODER_CNT > 3
564
   #if I2CPE_ENCODER_CNT > 3
590
 
587
 
591
     encoders[i].set_active(encoders[i].passes_test(true));
588
     encoders[i].set_active(encoders[i].passes_test(true));
592
 
589
 
593
-    #if I2CPE_ENC_4_AXIS == E_AXIS
594
-      encoders[i].set_homed();
595
-    #endif
590
+    TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_4_AXIS == E_AXIS) encoders[i].set_homed());
596
   #endif
591
   #endif
597
 
592
 
598
   #if I2CPE_ENCODER_CNT > 4
593
   #if I2CPE_ENCODER_CNT > 4
621
 
616
 
622
     encoders[i].set_active(encoders[i].passes_test(true));
617
     encoders[i].set_active(encoders[i].passes_test(true));
623
 
618
 
624
-    #if I2CPE_ENC_5_AXIS == E_AXIS
625
-      encoders[i].set_homed();
626
-    #endif
619
+    TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_5_AXIS == E_AXIS) encoders[i].set_homed());
627
   #endif
620
   #endif
628
 
621
 
629
   #if I2CPE_ENCODER_CNT > 5
622
   #if I2CPE_ENCODER_CNT > 5
652
 
645
 
653
     encoders[i].set_active(encoders[i].passes_test(true));
646
     encoders[i].set_active(encoders[i].passes_test(true));
654
 
647
 
655
-    #if I2CPE_ENC_6_AXIS == E_AXIS
656
-      encoders[i].set_homed();
657
-    #endif
648
+    TERN_(HAS_EXTRUDERS, if (I2CPE_ENC_6_AXIS == E_AXIS) encoders[i].set_homed());
658
   #endif
649
   #endif
659
 }
650
 }
660
 
651
 

+ 25
- 9
Marlin/src/feature/tmc_util.cpp 查看文件

757
     }
757
     }
758
   }
758
   }
759
 
759
 
760
-  static void tmc_debug_loop(const TMC_debug_enum i, const bool print_x, const bool print_y, const bool print_z, const bool print_e) {
760
+  static void tmc_debug_loop(
761
+    const TMC_debug_enum i,
762
+    LOGICAL_AXIS_LIST(const bool print_e, const bool print_x, const bool print_y, const bool print_z)
763
+  ) {
761
     if (print_x) {
764
     if (print_x) {
762
       #if AXIS_IS_TMC(X)
765
       #if AXIS_IS_TMC(X)
763
         tmc_status(stepperX, i);
766
         tmc_status(stepperX, i);
821
     SERIAL_EOL();
824
     SERIAL_EOL();
822
   }
825
   }
823
 
826
 
824
-  static void drv_status_loop(const TMC_drv_status_enum i, const bool print_x, const bool print_y, const bool print_z, const bool print_e) {
827
+  static void drv_status_loop(
828
+    const TMC_drv_status_enum i,
829
+    LOGICAL_AXIS_LIST(const bool print_e, const bool print_x, const bool print_y, const bool print_z)
830
+  ) {
825
     if (print_x) {
831
     if (print_x) {
826
       #if AXIS_IS_TMC(X)
832
       #if AXIS_IS_TMC(X)
827
         tmc_parse_drv_status(stepperX, i);
833
         tmc_parse_drv_status(stepperX, i);
889
    * M122 report functions
895
    * M122 report functions
890
    */
896
    */
891
 
897
 
892
-  void tmc_report_all(const bool print_x/*=true*/, const bool print_y/*=true*/, const bool print_z/*=true*/, const bool print_e/*=true*/) {
893
-    #define TMC_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL);  tmc_debug_loop(ITEM, print_x, print_y, print_z, print_e); }while(0)
894
-    #define DRV_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); drv_status_loop(ITEM, print_x, print_y, print_z, print_e); }while(0)
898
+  void tmc_report_all(
899
+    LOGICAL_AXIS_LIST(const bool print_e/*=true*/, const bool print_x/*=true*/, const bool print_y/*=true*/, const bool print_z/*=true*/)
900
+  ) {
901
+    #define TMC_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL);  tmc_debug_loop(ITEM, LOGICAL_AXIS_LIST(print_e, print_x, print_y, print_z)); }while(0)
902
+    #define DRV_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); drv_status_loop(ITEM, LOGICAL_AXIS_LIST(print_e, print_x, print_y, print_z)); }while(0)
903
+
895
     TMC_REPORT("\t",                 TMC_CODES);
904
     TMC_REPORT("\t",                 TMC_CODES);
896
     #if HAS_DRIVER(TMC2209)
905
     #if HAS_DRIVER(TMC2209)
897
       TMC_REPORT("Address\t",        TMC_UART_ADDR);
906
       TMC_REPORT("Address\t",        TMC_UART_ADDR);
1015
     }
1024
     }
1016
   #endif
1025
   #endif
1017
 
1026
 
1018
-  static void tmc_get_registers(TMC_get_registers_enum i, const bool print_x, const bool print_y, const bool print_z, const bool print_e) {
1027
+  static void tmc_get_registers(
1028
+    TMC_get_registers_enum i,
1029
+    LOGICAL_AXIS_LIST(const bool print_e, const bool print_x, const bool print_y, const bool print_z)
1030
+  ) {
1019
     if (print_x) {
1031
     if (print_x) {
1020
       #if AXIS_IS_TMC(X)
1032
       #if AXIS_IS_TMC(X)
1021
         tmc_get_registers(stepperX, i);
1033
         tmc_get_registers(stepperX, i);
1079
     SERIAL_EOL();
1091
     SERIAL_EOL();
1080
   }
1092
   }
1081
 
1093
 
1082
-  void tmc_get_registers(bool print_x, bool print_y, bool print_z, bool print_e) {
1083
-    #define _TMC_GET_REG(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); tmc_get_registers(ITEM, print_x, print_y, print_z, print_e); }while(0)
1094
+  void tmc_get_registers(
1095
+    LOGICAL_AXIS_LIST(bool print_e, bool print_x, bool print_y, bool print_z)
1096
+  ) {
1097
+    #define _TMC_GET_REG(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); tmc_get_registers(ITEM, LOGICAL_AXIS_LIST(print_e, print_x, print_y, print_z)); }while(0)
1084
     #define TMC_GET_REG(NAME, TABS) _TMC_GET_REG(STRINGIFY(NAME) TABS, TMC_GET_##NAME)
1098
     #define TMC_GET_REG(NAME, TABS) _TMC_GET_REG(STRINGIFY(NAME) TABS, TMC_GET_##NAME)
1085
     _TMC_GET_REG("\t", TMC_AXIS_CODES);
1099
     _TMC_GET_REG("\t", TMC_AXIS_CODES);
1086
     TMC_GET_REG(GCONF, "\t\t");
1100
     TMC_GET_REG(GCONF, "\t\t");
1214
   return test_result;
1228
   return test_result;
1215
 }
1229
 }
1216
 
1230
 
1217
-void test_tmc_connection(const bool test_x/*=true*/, const bool test_y/*=true*/, const bool test_z/*=true*/, const bool test_e/*=true*/) {
1231
+void test_tmc_connection(
1232
+  LOGICAL_AXIS_LIST(const bool test_e/*=true*/, const bool test_x/*=true*/, const bool test_y/*=true*/, const bool test_z/*=true*/)
1233
+) {
1218
   uint8_t axis_connection = 0;
1234
   uint8_t axis_connection = 0;
1219
 
1235
 
1220
   if (test_x) {
1236
   if (test_x) {

+ 10
- 4
Marlin/src/feature/tmc_util.h 查看文件

335
 #endif
335
 #endif
336
 
336
 
337
 void monitor_tmc_drivers();
337
 void monitor_tmc_drivers();
338
-void test_tmc_connection(const bool test_x=true, const bool test_y=true, const bool test_z=true, const bool test_e=true);
338
+void test_tmc_connection(
339
+  LOGICAL_AXIS_LIST(const bool test_e=true, const bool test_x=true, const bool test_y=true, const bool test_z=true)
340
+);
339
 
341
 
340
 #if ENABLED(TMC_DEBUG)
342
 #if ENABLED(TMC_DEBUG)
341
   #if ENABLED(MONITOR_DRIVER_STATUS)
343
   #if ENABLED(MONITOR_DRIVER_STATUS)
342
     void tmc_set_report_interval(const uint16_t update_interval);
344
     void tmc_set_report_interval(const uint16_t update_interval);
343
   #endif
345
   #endif
344
-  void tmc_report_all(const bool print_x=true, const bool print_y=true, const bool print_z=true, const bool print_e=true);
345
-  void tmc_get_registers(const bool print_x, const bool print_y, const bool print_z, const bool print_e);
346
+  void tmc_report_all(
347
+    LOGICAL_AXIS_LIST(const bool print_e=true, const bool print_x=true, const bool print_y=true, const bool print_z=true)
348
+  );
349
+  void tmc_get_registers(
350
+    LOGICAL_AXIS_LIST(const bool print_e, const bool print_x, const bool print_y, const bool print_z)
351
+  );
346
 #endif
352
 #endif
347
 
353
 
348
 /**
354
 /**
355
 #if USE_SENSORLESS
361
 #if USE_SENSORLESS
356
 
362
 
357
   // Track enabled status of stealthChop and only re-enable where applicable
363
   // Track enabled status of stealthChop and only re-enable where applicable
358
-  struct sensorless_t { bool x, y, z, x2, y2, z2, z3, z4; };
364
+  struct sensorless_t { bool LINEAR_AXIS_LIST(x, y, z), x2, y2, z2, z3, z4; };
359
 
365
 
360
   #if ENABLED(IMPROVE_HOMING_RELIABILITY)
366
   #if ENABLED(IMPROVE_HOMING_RELIABILITY)
361
     extern millis_t sg_guard_period;
367
     extern millis_t sg_guard_period;

+ 19
- 8
Marlin/src/gcode/calibrate/G28.cpp 查看文件

321
 
321
 
322
   #else
322
   #else
323
 
323
 
324
+    #define _UNSAFE(A) (homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(A##_AXIS))))
325
+
324
     const bool homeZ = parser.seen_test('Z'),
326
     const bool homeZ = parser.seen_test('Z'),
325
-               needX = homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(X_AXIS))),
326
-               needY = homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(Y_AXIS))),
327
-               homeX = needX || parser.seen_test('X'), homeY = needY || parser.seen_test('Y'),
328
-               home_all = homeX == homeY && homeX == homeZ, // All or None
329
-               doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ;
327
+               LINEAR_AXIS_LIST( // Other axes should be homed before Z safe-homing
328
+                 needX = _UNSAFE(X), needY = _UNSAFE(Y), needZ = false // UNUSED
329
+               ),
330
+               LINEAR_AXIS_LIST( // Home each axis if needed or flagged
331
+                 homeX = needX || parser.seen_test('X'),
332
+                 homeY = needY || parser.seen_test('Y'),
333
+                 homeZZ = homeZ // UNUSED
334
+               ),
335
+               // Home-all if all or none are flagged
336
+               home_all = true LINEAR_AXIS_GANG(&& homeX == homeX, && homeX == homeY, && homeX == homeZ),
337
+               LINEAR_AXIS_LIST(doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ);
338
+
339
+   UNUSED(needZ);
340
+   UNUSED(homeZZ);
330
 
341
 
331
     #if ENABLED(HOME_Z_FIRST)
342
     #if ENABLED(HOME_Z_FIRST)
332
 
343
 
336
 
347
 
337
     const float z_homing_height = parser.seenval('R') ? parser.value_linear_units() : Z_HOMING_HEIGHT;
348
     const float z_homing_height = parser.seenval('R') ? parser.value_linear_units() : Z_HOMING_HEIGHT;
338
 
349
 
339
-    if (z_homing_height && (doX || doY || TERN0(Z_SAFE_HOMING, doZ))) {
350
+    if (z_homing_height && (0 LINEAR_AXIS_GANG(|| doX, || doY, || TERN0(Z_SAFE_HOMING, doZ)))) {
340
       // Raise Z before homing any other axes and z is not already high enough (never lower z)
351
       // Raise Z before homing any other axes and z is not already high enough (never lower z)
341
       if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Raise Z (before homing) by ", z_homing_height);
352
       if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Raise Z (before homing) by ", z_homing_height);
342
       do_z_clearance(z_homing_height);
353
       do_z_clearance(z_homing_height);
469
     #if HAS_CURRENT_HOME(Y2)
480
     #if HAS_CURRENT_HOME(Y2)
470
       stepperY2.rms_current(tmc_save_current_Y2);
481
       stepperY2.rms_current(tmc_save_current_Y2);
471
     #endif
482
     #endif
472
-  #endif
483
+  #endif // HAS_HOMING_CURRENT
473
 
484
 
474
   ui.refresh();
485
   ui.refresh();
475
 
486
 
490
     static constexpr AxisEnum L64XX_axis_xref[MAX_L64XX] = {
501
     static constexpr AxisEnum L64XX_axis_xref[MAX_L64XX] = {
491
       X_AXIS, Y_AXIS, Z_AXIS,
502
       X_AXIS, Y_AXIS, Z_AXIS,
492
       X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS,
503
       X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS,
493
-      E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS
504
+      E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS, E_AXIS
494
     };
505
     };
495
     for (uint8_t j = 1; j <= L64XX::chain[0]; j++) {
506
     for (uint8_t j = 1; j <= L64XX::chain[0]; j++) {
496
       const uint8_t cv = L64XX::chain[j];
507
       const uint8_t cv = L64XX::chain[j];

+ 8
- 4
Marlin/src/gcode/calibrate/G425.cpp 查看文件

307
 
307
 
308
   // The difference between the known and the measured location
308
   // The difference between the known and the measured location
309
   // of the calibration object is the positional error
309
   // of the calibration object is the positional error
310
-  m.pos_error.x = TERN0(HAS_X_CENTER, true_center.x - m.obj_center.x);
311
-  m.pos_error.y = TERN0(HAS_Y_CENTER, true_center.y - m.obj_center.y);
312
-  m.pos_error.z = true_center.z - m.obj_center.z;
310
+  LINEAR_AXIS_CODE(
311
+    m.pos_error.x = TERN0(HAS_X_CENTER, true_center.x - m.obj_center.x),
312
+    m.pos_error.y = TERN0(HAS_Y_CENTER, true_center.y - m.obj_center.y),
313
+    m.pos_error.z = true_center.z - m.obj_center.z
314
+  );
313
 }
315
 }
314
 
316
 
315
 #if ENABLED(CALIBRATION_REPORTING)
317
 #if ENABLED(CALIBRATION_REPORTING)
455
       // New scope for TEMPORARY_BACKLASH_CORRECTION
457
       // New scope for TEMPORARY_BACKLASH_CORRECTION
456
       TEMPORARY_BACKLASH_CORRECTION(all_on);
458
       TEMPORARY_BACKLASH_CORRECTION(all_on);
457
       TEMPORARY_BACKLASH_SMOOTHING(0.0f);
459
       TEMPORARY_BACKLASH_SMOOTHING(0.0f);
458
-      const xyz_float_t move = { AXIS_CAN_CALIBRATE(X) * 3, AXIS_CAN_CALIBRATE(Y) * 3, AXIS_CAN_CALIBRATE(Z) * 3 };
460
+      const xyz_float_t move = LINEAR_AXIS_ARRAY(
461
+        AXIS_CAN_CALIBRATE(X) * 3, AXIS_CAN_CALIBRATE(Y) * 3, AXIS_CAN_CALIBRATE(Z) * 3
462
+      );
459
       current_position += move; calibration_move();
463
       current_position += move; calibration_move();
460
       current_position -= move; calibration_move();
464
       current_position -= move; calibration_move();
461
     }
465
     }

+ 6
- 4
Marlin/src/gcode/calibrate/M425.cpp 查看文件

48
 
48
 
49
   auto axis_can_calibrate = [](const uint8_t a) {
49
   auto axis_can_calibrate = [](const uint8_t a) {
50
     switch (a) {
50
     switch (a) {
51
-      default:
52
-      case X_AXIS: return AXIS_CAN_CALIBRATE(X);
53
-      case Y_AXIS: return AXIS_CAN_CALIBRATE(Y);
54
-      case Z_AXIS: return AXIS_CAN_CALIBRATE(Z);
51
+      default: return false;
52
+      LINEAR_AXIS_CODE(
53
+        case X_AXIS: return AXIS_CAN_CALIBRATE(X),
54
+        case Y_AXIS: return AXIS_CAN_CALIBRATE(Y),
55
+        case Z_AXIS: return AXIS_CAN_CALIBRATE(Z)
56
+      );
55
     }
57
     }
56
   };
58
   };
57
 
59
 

+ 13
- 14
Marlin/src/gcode/config/M200-M205.cpp 查看文件

88
 
88
 
89
   LOOP_LOGICAL_AXES(i) {
89
   LOOP_LOGICAL_AXES(i) {
90
     if (parser.seenval(axis_codes[i])) {
90
     if (parser.seenval(axis_codes[i])) {
91
-      const uint8_t a = (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i);
91
+      const uint8_t a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i), i);
92
       planner.set_max_acceleration(a, parser.value_axis_units((AxisEnum)a));
92
       planner.set_max_acceleration(a, parser.value_axis_units((AxisEnum)a));
93
     }
93
     }
94
   }
94
   }
106
 
106
 
107
   LOOP_LOGICAL_AXES(i)
107
   LOOP_LOGICAL_AXES(i)
108
     if (parser.seenval(axis_codes[i])) {
108
     if (parser.seenval(axis_codes[i])) {
109
-      const uint8_t a = (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i);
109
+      const uint8_t a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i), i);
110
       planner.set_max_feedrate(a, parser.value_axis_units((AxisEnum)a));
110
       planner.set_max_feedrate(a, parser.value_axis_units((AxisEnum)a));
111
     }
111
     }
112
 }
112
 }
165
     }
165
     }
166
   #endif
166
   #endif
167
   #if HAS_CLASSIC_JERK
167
   #if HAS_CLASSIC_JERK
168
-    if (parser.seenval('X')) planner.set_max_jerk(X_AXIS, parser.value_linear_units());
169
-    if (parser.seenval('Y')) planner.set_max_jerk(Y_AXIS, parser.value_linear_units());
170
-    if (parser.seenval('Z')) {
171
-      planner.set_max_jerk(Z_AXIS, parser.value_linear_units());
172
-      #if HAS_MESH && DISABLED(LIMITED_JERK_EDITING)
173
-        if (planner.max_jerk.z <= 0.1f)
174
-          SERIAL_ECHOLNPGM("WARNING! Low Z Jerk may lead to unwanted pauses.");
175
-      #endif
176
-    }
177
-    #if HAS_CLASSIC_E_JERK
178
-      if (parser.seenval('E')) planner.set_max_jerk(E_AXIS, parser.value_linear_units());
168
+    bool seenZ = false;
169
+    LOGICAL_AXIS_CODE(
170
+      if (parser.seenval('E')) planner.set_max_jerk(E_AXIS, parser.value_linear_units()),
171
+      if (parser.seenval('X')) planner.set_max_jerk(X_AXIS, parser.value_linear_units()),
172
+      if (parser.seenval('Y')) planner.set_max_jerk(Y_AXIS, parser.value_linear_units()),
173
+      if ((seenZ = parser.seenval('Z'))) planner.set_max_jerk(Z_AXIS, parser.value_linear_units())
174
+    );
175
+    #if HAS_MESH && DISABLED(LIMITED_JERK_EDITING)
176
+      if (seenZ && planner.max_jerk.z <= 0.1f)
177
+        SERIAL_ECHOLNPGM("WARNING! Low Z Jerk may lead to unwanted pauses.");
179
     #endif
178
     #endif
180
-  #endif
179
+  #endif // HAS_CLASSIC_JERK
181
 }
180
 }

+ 24
- 19
Marlin/src/gcode/config/M92.cpp 查看文件

25
 
25
 
26
 void report_M92(const bool echo=true, const int8_t e=-1) {
26
 void report_M92(const bool echo=true, const int8_t e=-1) {
27
   if (echo) SERIAL_ECHO_START(); else SERIAL_CHAR(' ');
27
   if (echo) SERIAL_ECHO_START(); else SERIAL_CHAR(' ');
28
-  SERIAL_ECHOPAIR_P(PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]),
29
-                          SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]),
30
-                          SP_Z_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Z_AXIS]));
31
-  #if DISABLED(DISTINCT_E_FACTORS)
28
+  SERIAL_ECHOPAIR_P(LIST_N(DOUBLE(LINEAR_AXES),
29
+    PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]),
30
+    SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]),
31
+    SP_Z_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Z_AXIS])
32
+  ));
33
+  #if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS)
32
     SERIAL_ECHOPAIR_P(SP_E_STR, VOLUMETRIC_UNIT(planner.settings.axis_steps_per_mm[E_AXIS]));
34
     SERIAL_ECHOPAIR_P(SP_E_STR, VOLUMETRIC_UNIT(planner.settings.axis_steps_per_mm[E_AXIS]));
33
   #endif
35
   #endif
34
   SERIAL_EOL();
36
   SERIAL_EOL();
64
   if (target_extruder < 0) return;
66
   if (target_extruder < 0) return;
65
 
67
 
66
   // No arguments? Show M92 report.
68
   // No arguments? Show M92 report.
67
-  if (!parser.seen("XYZE" TERN_(MAGIC_NUMBERS_GCODE, "HL")))
68
-    return report_M92(true, target_extruder);
69
+  if (!parser.seen(
70
+    LOGICAL_AXIS_GANG("E", "X", "Y", "Z")
71
+    TERN_(MAGIC_NUMBERS_GCODE, "HL")
72
+  )) return report_M92(true, target_extruder);
69
 
73
 
70
   LOOP_LOGICAL_AXES(i) {
74
   LOOP_LOGICAL_AXES(i) {
71
     if (parser.seenval(axis_codes[i])) {
75
     if (parser.seenval(axis_codes[i])) {
72
-      if (i == E_AXIS) {
73
-        const float value = parser.value_per_axis_units((AxisEnum)(E_AXIS_N(target_extruder)));
74
-        if (value < 20) {
75
-          float factor = planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] / value; // increase e constants if M92 E14 is given for netfab.
76
-          #if HAS_CLASSIC_JERK && HAS_CLASSIC_E_JERK
77
-            planner.max_jerk.e *= factor;
78
-          #endif
79
-          planner.settings.max_feedrate_mm_s[E_AXIS_N(target_extruder)] *= factor;
80
-          planner.max_acceleration_steps_per_s2[E_AXIS_N(target_extruder)] *= factor;
81
-        }
82
-        planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] = value;
83
-      }
84
-      else {
76
+      if (TERN1(HAS_EXTRUDERS, i != E_AXIS))
85
         planner.settings.axis_steps_per_mm[i] = parser.value_per_axis_units((AxisEnum)i);
77
         planner.settings.axis_steps_per_mm[i] = parser.value_per_axis_units((AxisEnum)i);
78
+      else {
79
+        #if HAS_EXTRUDERS
80
+          const float value = parser.value_per_axis_units((AxisEnum)(E_AXIS_N(target_extruder)));
81
+          if (value < 20) {
82
+            float factor = planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] / value; // increase e constants if M92 E14 is given for netfab.
83
+            #if HAS_CLASSIC_JERK && HAS_CLASSIC_E_JERK
84
+              planner.max_jerk.e *= factor;
85
+            #endif
86
+            planner.settings.max_feedrate_mm_s[E_AXIS_N(target_extruder)] *= factor;
87
+            planner.max_acceleration_steps_per_s2[E_AXIS_N(target_extruder)] *= factor;
88
+          }
89
+          planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] = value;
90
+        #endif
86
       }
91
       }
87
     }
92
     }
88
   }
93
   }

+ 14
- 10
Marlin/src/gcode/control/M17_M18_M84.cpp 查看文件

33
  * M17: Enable stepper motors
33
  * M17: Enable stepper motors
34
  */
34
  */
35
 void GcodeSuite::M17() {
35
 void GcodeSuite::M17() {
36
-  if (parser.seen("XYZE")) {
37
-    if (parser.seen_test('X')) ENABLE_AXIS_X();
38
-    if (parser.seen_test('Y')) ENABLE_AXIS_Y();
39
-    if (parser.seen_test('Z')) ENABLE_AXIS_Z();
40
-    if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen_test('E'))) enable_e_steppers();
36
+  if (parser.seen(LOGICAL_AXIS_GANG("E", "X", "Y", "Z"))) {
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
+    );
41
   }
43
   }
42
   else {
44
   else {
43
     LCD_MESSAGEPGM(MSG_NO_MOVE);
45
     LCD_MESSAGEPGM(MSG_NO_MOVE);
54
     stepper_inactive_time = parser.value_millis_from_seconds();
56
     stepper_inactive_time = parser.value_millis_from_seconds();
55
   }
57
   }
56
   else {
58
   else {
57
-    if (parser.seen("XYZE")) {
59
+    if (parser.seen(LOGICAL_AXIS_GANG("E", "X", "Y", "Z"))) {
58
       planner.synchronize();
60
       planner.synchronize();
59
-      if (parser.seen_test('X')) DISABLE_AXIS_X();
60
-      if (parser.seen_test('Y')) DISABLE_AXIS_Y();
61
-      if (parser.seen_test('Z')) DISABLE_AXIS_Z();
62
-      if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen_test('E'))) disable_e_steppers();
61
+      LOGICAL_AXIS_CODE(
62
+        if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen_test('E'))) disable_e_steppers(),
63
+        if (parser.seen_test('X'))        DISABLE_AXIS_X(),
64
+        if (parser.seen_test('Y'))        DISABLE_AXIS_Y(),
65
+        if (parser.seen_test('Z'))        DISABLE_AXIS_Z()
66
+      );
63
     }
67
     }
64
     else
68
     else
65
       planner.finish_and_disable();
69
       planner.finish_and_disable();

+ 7
- 5
Marlin/src/gcode/feature/pause/G61.cpp 查看文件

69
     SYNC_E(stored_position[slot].e);
69
     SYNC_E(stored_position[slot].e);
70
   }
70
   }
71
   else {
71
   else {
72
-    if (parser.seen("XYZ")) {
72
+    if (parser.seen(LINEAR_AXIS_GANG("X", "Y", "Z"))) {
73
       DEBUG_ECHOPAIR(STR_RESTORING_POS " S", slot);
73
       DEBUG_ECHOPAIR(STR_RESTORING_POS " S", slot);
74
       LOOP_LINEAR_AXES(i) {
74
       LOOP_LINEAR_AXES(i) {
75
         destination[i] = parser.seen(AXIS_CHAR(i))
75
         destination[i] = parser.seen(AXIS_CHAR(i))
82
       // Move to the saved position
82
       // Move to the saved position
83
       prepare_line_to_destination();
83
       prepare_line_to_destination();
84
     }
84
     }
85
-    if (parser.seen_test('E')) {
86
-      DEBUG_ECHOLNPAIR(STR_RESTORING_POS " S", slot, " E", current_position.e, "=>", stored_position[slot].e);
87
-      SYNC_E(stored_position[slot].e);
88
-    }
85
+    #if HAS_EXTRUDERS
86
+      if (parser.seen_test('E')) {
87
+        DEBUG_ECHOLNPAIR(STR_RESTORING_POS " S", slot, " E", current_position.e, "=>", stored_position[slot].e);
88
+        SYNC_E(stored_position[slot].e);
89
+      }
90
+    #endif
89
   }
91
   }
90
 
92
 
91
   feedrate_mm_s = saved_feedrate;
93
   feedrate_mm_s = saved_feedrate;

+ 13
- 5
Marlin/src/gcode/feature/trinamic/M122.cpp 查看文件

49
       tmc_set_report_interval(interval);
49
       tmc_set_report_interval(interval);
50
     #endif
50
     #endif
51
 
51
 
52
-    if (parser.seen_test('V'))
53
-      tmc_get_registers(print_axis.x, print_axis.y, print_axis.z, print_axis.e);
54
-    else
55
-      tmc_report_all(print_axis.x, print_axis.y, print_axis.z, print_axis.e);
52
+    if (parser.seen_test('V')) {
53
+      tmc_get_registers(
54
+        LOGICAL_AXIS_LIST(print_axis.e, print_axis.x, print_axis.y, print_axis.z)
55
+      );
56
+    }
57
+    else {
58
+      tmc_report_all(
59
+        LOGICAL_AXIS_LIST(print_axis.e, print_axis.x, print_axis.y, print_axis.z)
60
+      );
61
+    }
56
   #endif
62
   #endif
57
 
63
 
58
-  test_tmc_connection(print_axis.x, print_axis.y, print_axis.z, print_axis.e);
64
+  test_tmc_connection(
65
+    LOGICAL_AXIS_LIST(print_axis.e, print_axis.x, print_axis.y, print_axis.z)
66
+  );
59
 }
67
 }
60
 
68
 
61
 #endif // HAS_TRINAMIC_CONFIG
69
 #endif // HAS_TRINAMIC_CONFIG

+ 14
- 12
Marlin/src/gcode/gcode.cpp 查看文件

74
 
74
 
75
 // Relative motion mode for each logical axis
75
 // Relative motion mode for each logical axis
76
 static constexpr xyze_bool_t ar_init = AXIS_RELATIVE_MODES;
76
 static constexpr xyze_bool_t ar_init = AXIS_RELATIVE_MODES;
77
-uint8_t GcodeSuite::axis_relative = (
78
-    (ar_init.x ? _BV(REL_X) : 0)
79
-  | (ar_init.y ? _BV(REL_Y) : 0)
80
-  | (ar_init.z ? _BV(REL_Z) : 0)
81
-  | (ar_init.e ? _BV(REL_E) : 0)
77
+uint8_t GcodeSuite::axis_relative = 0 LOGICAL_AXIS_GANG(
78
+  | (ar_init.e << REL_E),
79
+  | (ar_init.x << REL_X),
80
+  | (ar_init.y << REL_Y),
81
+  | (ar_init.z << REL_Z)
82
 );
82
 );
83
 
83
 
84
 #if EITHER(HAS_AUTO_REPORTING, HOST_KEEPALIVE_FEATURE)
84
 #if EITHER(HAS_AUTO_REPORTING, HOST_KEEPALIVE_FEATURE)
161
       destination[i] = current_position[i];
161
       destination[i] = current_position[i];
162
   }
162
   }
163
 
163
 
164
-  // Get new E position, whether absolute or relative
165
-  if ( (seen.e = parser.seenval('E')) ) {
166
-    const float v = parser.value_axis_units(E_AXIS);
167
-    destination.e = axis_is_relative(E_AXIS) ? current_position.e + v : v;
168
-  }
169
-  else
170
-    destination.e = current_position.e;
164
+  #if HAS_EXTRUDERS
165
+    // Get new E position, whether absolute or relative
166
+    if ( (seen.e = parser.seenval('E')) ) {
167
+      const float v = parser.value_axis_units(E_AXIS);
168
+      destination.e = axis_is_relative(E_AXIS) ? current_position.e + v : v;
169
+    }
170
+    else
171
+      destination.e = current_position.e;
172
+  #endif
171
 
173
 
172
   #if ENABLED(POWER_LOSS_RECOVERY) && !PIN_EXISTS(POWER_LOSS)
174
   #if ENABLED(POWER_LOSS_RECOVERY) && !PIN_EXISTS(POWER_LOSS)
173
     // Only update power loss recovery on moves with E
175
     // Only update power loss recovery on moves with E

+ 23
- 14
Marlin/src/gcode/gcode.h 查看文件

314
   #define HAS_FAST_MOVES 1
314
   #define HAS_FAST_MOVES 1
315
 #endif
315
 #endif
316
 
316
 
317
-enum AxisRelative : uint8_t { REL_X, REL_Y, REL_Z, REL_E, E_MODE_ABS, E_MODE_REL };
317
+enum AxisRelative : uint8_t {
318
+  LOGICAL_AXIS_LIST(REL_E, REL_X, REL_Y, REL_Z)
319
+  #if HAS_EXTRUDERS
320
+    , E_MODE_ABS, E_MODE_REL
321
+  #endif
322
+};
318
 
323
 
319
 extern const char G28_STR[];
324
 extern const char G28_STR[];
320
 
325
 
324
   static uint8_t axis_relative;
329
   static uint8_t axis_relative;
325
 
330
 
326
   static inline bool axis_is_relative(const AxisEnum a) {
331
   static inline bool axis_is_relative(const AxisEnum a) {
327
-    if (a == E_AXIS) {
328
-      if (TEST(axis_relative, E_MODE_REL)) return true;
329
-      if (TEST(axis_relative, E_MODE_ABS)) return false;
330
-    }
332
+    #if HAS_EXTRUDERS
333
+      if (a == E_AXIS) {
334
+        if (TEST(axis_relative, E_MODE_REL)) return true;
335
+        if (TEST(axis_relative, E_MODE_ABS)) return false;
336
+      }
337
+    #endif
331
     return TEST(axis_relative, a);
338
     return TEST(axis_relative, a);
332
   }
339
   }
333
   static inline void set_relative_mode(const bool rel) {
340
   static inline void set_relative_mode(const bool rel) {
334
-    axis_relative = rel ? _BV(REL_X) | _BV(REL_Y) | _BV(REL_Z) | _BV(REL_E) : 0;
335
-  }
336
-  static inline void set_e_relative() {
337
-    CBI(axis_relative, E_MODE_ABS);
338
-    SBI(axis_relative, E_MODE_REL);
339
-  }
340
-  static inline void set_e_absolute() {
341
-    CBI(axis_relative, E_MODE_REL);
342
-    SBI(axis_relative, E_MODE_ABS);
341
+    axis_relative = rel ? (0 LOGICAL_AXIS_GANG(| _BV(REL_E), | _BV(REL_X), | _BV(REL_Y), | _BV(REL_Z))) : 0;
343
   }
342
   }
343
+  #if HAS_EXTRUDERS
344
+    static inline void set_e_relative() {
345
+      CBI(axis_relative, E_MODE_ABS);
346
+      SBI(axis_relative, E_MODE_REL);
347
+    }
348
+    static inline void set_e_absolute() {
349
+      CBI(axis_relative, E_MODE_REL);
350
+      SBI(axis_relative, E_MODE_ABS);
351
+    }
352
+  #endif
344
 
353
 
345
   #if ENABLED(CNC_WORKSPACE_PLANES)
354
   #if ENABLED(CNC_WORKSPACE_PLANES)
346
     /**
355
     /**

+ 26
- 11
Marlin/src/gcode/geometry/G92.cpp 查看文件

48
  */
48
  */
49
 void GcodeSuite::G92() {
49
 void GcodeSuite::G92() {
50
 
50
 
51
-  bool sync_E = false, sync_XYZE = false;
51
+  #if HAS_EXTRUDERS
52
+    bool sync_E = false;
53
+  #endif
54
+  bool sync_XYZE = false;
52
 
55
 
53
   #if USE_GCODE_SUBCODES
56
   #if USE_GCODE_SUBCODES
54
     const uint8_t subcode_G92 = parser.subcode;
57
     const uint8_t subcode_G92 = parser.subcode;
72
       case 9:                                                         // G92.9 - Set Current Position directly (like Marlin 1.0)
75
       case 9:                                                         // G92.9 - Set Current Position directly (like Marlin 1.0)
73
         LOOP_LOGICAL_AXES(i) {
76
         LOOP_LOGICAL_AXES(i) {
74
           if (parser.seenval(axis_codes[i])) {
77
           if (parser.seenval(axis_codes[i])) {
75
-            if (i == E_AXIS) sync_E = true; else sync_XYZE = true;
78
+            if (TERN1(HAS_EXTRUDERS, i != E_AXIS))
79
+              sync_XYZE = true;
80
+            else {
81
+              TERN_(HAS_EXTRUDERS, sync_E = true);
82
+            }
76
             current_position[i] = parser.value_axis_units((AxisEnum)i);
83
             current_position[i] = parser.value_axis_units((AxisEnum)i);
77
           }
84
           }
78
         }
85
         }
83
       LOOP_LOGICAL_AXES(i) {
90
       LOOP_LOGICAL_AXES(i) {
84
         if (parser.seenval(axis_codes[i])) {
91
         if (parser.seenval(axis_codes[i])) {
85
           const float l = parser.value_axis_units((AxisEnum)i),       // Given axis coordinate value, converted to millimeters
92
           const float l = parser.value_axis_units((AxisEnum)i),       // Given axis coordinate value, converted to millimeters
86
-                      v = i == E_AXIS ? l : LOGICAL_TO_NATIVE(l, i),  // Axis position in NATIVE space (applying the existing offset)
93
+                      v = TERN0(HAS_EXTRUDERS, i == E_AXIS) ? l : LOGICAL_TO_NATIVE(l, i),  // Axis position in NATIVE space (applying the existing offset)
87
                       d = v - current_position[i];                    // How much is the current axis position altered by?
94
                       d = v - current_position[i];                    // How much is the current axis position altered by?
88
           if (!NEAR_ZERO(d)) {
95
           if (!NEAR_ZERO(d)) {
89
             #if HAS_POSITION_SHIFT && !IS_SCARA                       // When using workspaces...
96
             #if HAS_POSITION_SHIFT && !IS_SCARA                       // When using workspaces...
90
-              if (i == E_AXIS) {
91
-                sync_E = true;
92
-                current_position.e = v;                               // ...E is still set directly
97
+              if (TERN1(HAS_EXTRUDERS, i != E_AXIS)) {
98
+                position_shift[i] += d;                               // ...most axes offset the workspace...
99
+                update_workspace_offset((AxisEnum)i);
93
               }
100
               }
94
               else {
101
               else {
95
-                position_shift[i] += d;                               // ...but other axes offset the workspace.
96
-                update_workspace_offset((AxisEnum)i);
102
+                #if HAS_EXTRUDERS
103
+                  sync_E = true;
104
+                  current_position.e = v;                             // ...but E is set directly
105
+                #endif
97
               }
106
               }
98
             #else                                                     // Without workspaces...
107
             #else                                                     // Without workspaces...
99
-              if (i == E_AXIS) sync_E = true; else sync_XYZE = true;
108
+              if (TERN1(HAS_EXTRUDERS, i != E_AXIS))
109
+                sync_XYZE = true;
110
+              else {
111
+                TERN_(HAS_EXTRUDERS, sync_E = true);
112
+              }
100
               current_position[i] = v;                                // ...set Current Position directly (like Marlin 1.0)
113
               current_position[i] = v;                                // ...set Current Position directly (like Marlin 1.0)
101
             #endif
114
             #endif
102
           }
115
           }
111
       coordinate_system[active_coordinate_system] = position_shift;
124
       coordinate_system[active_coordinate_system] = position_shift;
112
   #endif
125
   #endif
113
 
126
 
114
-  if   (sync_XYZE) sync_plan_position();
115
-  else if (sync_E) sync_plan_position_e();
127
+  if (sync_XYZE) sync_plan_position();
128
+  #if HAS_EXTRUDERS
129
+    else if (sync_E) sync_plan_position_e();
130
+  #endif
116
 
131
 
117
   IF_DISABLED(DIRECT_STEPPING, report_current_position());
132
   IF_DISABLED(DIRECT_STEPPING, report_current_position());
118
 }
133
 }

+ 1
- 1
Marlin/src/gcode/host/M114.cpp 查看文件

170
 
170
 
171
     SERIAL_ECHOPGM("FromStp:");
171
     SERIAL_ECHOPGM("FromStp:");
172
     get_cartesian_from_steppers();  // writes 'cartes' (with forward kinematics)
172
     get_cartesian_from_steppers();  // writes 'cartes' (with forward kinematics)
173
-    xyze_pos_t from_steppers = { cartes.x, cartes.y, cartes.z, planner.get_axis_position_mm(E_AXIS) };
173
+    xyze_pos_t from_steppers = LOGICAL_AXIS_ARRAY(planner.get_axis_position_mm(E_AXIS), cartes.x, cartes.y, cartes.z);
174
     report_all_axis_pos(from_steppers);
174
     report_all_axis_pos(from_steppers);
175
 
175
 
176
     const xyze_float_t diff = from_steppers - leveled;
176
     const xyze_float_t diff = from_steppers - leveled;

+ 6
- 4
Marlin/src/gcode/motion/G0_G1.cpp 查看文件

49
   if (IsRunning()
49
   if (IsRunning()
50
     #if ENABLED(NO_MOTION_BEFORE_HOMING)
50
     #if ENABLED(NO_MOTION_BEFORE_HOMING)
51
       && !homing_needed_error(
51
       && !homing_needed_error(
52
-          (parser.seen_test('X') ? _BV(X_AXIS) : 0)
53
-        | (parser.seen_test('Y') ? _BV(Y_AXIS) : 0)
54
-        | (parser.seen_test('Z') ? _BV(Z_AXIS) : 0) )
52
+        LINEAR_AXIS_GANG(
53
+            (parser.seen_test('X') ? _BV(X_AXIS) : 0),
54
+          | (parser.seen_test('Y') ? _BV(Y_AXIS) : 0),
55
+          | (parser.seen_test('Z') ? _BV(Z_AXIS) : 0))
56
+      )
55
     #endif
57
     #endif
56
   ) {
58
   ) {
57
     TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_RUNNING));
59
     TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_RUNNING));
83
 
85
 
84
       if (MIN_AUTORETRACT <= MAX_AUTORETRACT) {
86
       if (MIN_AUTORETRACT <= MAX_AUTORETRACT) {
85
         // When M209 Autoretract is enabled, convert E-only moves to firmware retract/recover moves
87
         // When M209 Autoretract is enabled, convert E-only moves to firmware retract/recover moves
86
-        if (fwretract.autoretract_enabled && parser.seen('E') && !parser.seen("XYZ")) {
88
+        if (fwretract.autoretract_enabled && parser.seen_test('E') && !parser.seen(LINEAR_AXIS_GANG("X", "Y", "Z"))) {
87
           const float echange = destination.e - current_position.e;
89
           const float echange = destination.e - current_position.e;
88
           // Is this a retract or recover move?
90
           // Is this a retract or recover move?
89
           if (WITHIN(ABS(echange), MIN_AUTORETRACT, MAX_AUTORETRACT) && fwretract.retracted[active_extruder] == (echange > 0.0)) {
91
           if (WITHIN(ABS(echange), MIN_AUTORETRACT, MAX_AUTORETRACT) && fwretract.retracted[active_extruder] == (echange > 0.0)) {

+ 22
- 9
Marlin/src/gcode/motion/G2_G3.cpp 查看文件

109
     #endif
109
     #endif
110
   }
110
   }
111
 
111
 
112
-  float linear_travel = cart[l_axis] - start_L,
113
-        extruder_travel = cart.e - current_position.e;
112
+  float linear_travel = cart[l_axis] - start_L;
113
+
114
+  #if HAS_EXTRUDERS
115
+    float extruder_travel = cart.e - current_position.e;
116
+  #endif
114
 
117
 
115
   // If circling around...
118
   // If circling around...
116
   if (ENABLED(ARC_P_CIRCLES) && circles) {
119
   if (ENABLED(ARC_P_CIRCLES) && circles) {
117
     const float total_angular = angular_travel + circles * RADIANS(360),  // Total rotation with all circles and remainder
120
     const float total_angular = angular_travel + circles * RADIANS(360),  // Total rotation with all circles and remainder
118
               part_per_circle = RADIANS(360) / total_angular,             // Each circle's part of the total
121
               part_per_circle = RADIANS(360) / total_angular,             // Each circle's part of the total
119
-                 l_per_circle = linear_travel * part_per_circle,          // L movement per circle
120
-                 e_per_circle = extruder_travel * part_per_circle;        // E movement per circle
122
+                 l_per_circle = linear_travel * part_per_circle;          // L movement per circle
123
+
124
+    #if HAS_EXTRUDERS
125
+      const float e_per_circle = extruder_travel * part_per_circle;       // E movement per circle
126
+    #endif
127
+
121
     xyze_pos_t temp_position = current_position;                          // for plan_arc to compare to current_position
128
     xyze_pos_t temp_position = current_position;                          // for plan_arc to compare to current_position
122
     for (uint16_t n = circles; n--;) {
129
     for (uint16_t n = circles; n--;) {
123
-      temp_position.e += e_per_circle;                                    // Destination E axis
130
+      TERN_(HAS_EXTRUDERS, temp_position.e += e_per_circle);              // Destination E axis
124
       temp_position[l_axis] += l_per_circle;                              // Destination L axis
131
       temp_position[l_axis] += l_per_circle;                              // Destination L axis
125
       plan_arc(temp_position, offset, clockwise, 0);                      // Plan a single whole circle
132
       plan_arc(temp_position, offset, clockwise, 0);                      // Plan a single whole circle
126
     }
133
     }
127
     linear_travel = cart[l_axis] - current_position[l_axis];
134
     linear_travel = cart[l_axis] - current_position[l_axis];
128
-    extruder_travel = cart.e - current_position.e;
135
+    #if HAS_EXTRUDERS
136
+      extruder_travel = cart.e - current_position.e;
137
+    #endif
129
   }
138
   }
130
 
139
 
131
   const float flat_mm = radius * angular_travel,
140
   const float flat_mm = radius * angular_travel,
179
   xyze_pos_t raw;
188
   xyze_pos_t raw;
180
   const float theta_per_segment = angular_travel / segments,
189
   const float theta_per_segment = angular_travel / segments,
181
               linear_per_segment = linear_travel / segments,
190
               linear_per_segment = linear_travel / segments,
182
-              extruder_per_segment = extruder_travel / segments,
183
               sq_theta_per_segment = sq(theta_per_segment),
191
               sq_theta_per_segment = sq(theta_per_segment),
184
               sin_T = theta_per_segment - sq_theta_per_segment * theta_per_segment / 6,
192
               sin_T = theta_per_segment - sq_theta_per_segment * theta_per_segment / 6,
185
               cos_T = 1 - 0.5f * sq_theta_per_segment; // Small angle approximation
193
               cos_T = 1 - 0.5f * sq_theta_per_segment; // Small angle approximation
186
 
194
 
195
+  #if HAS_EXTRUDERS
196
+    const float extruder_per_segment = extruder_travel / segments;
197
+  #endif
198
+
187
   // Initialize the linear axis
199
   // Initialize the linear axis
188
   raw[l_axis] = current_position[l_axis];
200
   raw[l_axis] = current_position[l_axis];
189
 
201
 
190
   // Initialize the extruder axis
202
   // Initialize the extruder axis
191
-  raw.e = current_position.e;
203
+  TERN_(HAS_EXTRUDERS, raw.e = current_position.e);
192
 
204
 
193
   #if ENABLED(SCARA_FEEDRATE_SCALING)
205
   #if ENABLED(SCARA_FEEDRATE_SCALING)
194
     const float inv_duration = scaled_fr_mm_s / seg_length;
206
     const float inv_duration = scaled_fr_mm_s / seg_length;
240
     #else
252
     #else
241
       raw[l_axis] += linear_per_segment;
253
       raw[l_axis] += linear_per_segment;
242
     #endif
254
     #endif
243
-    raw.e += extruder_per_segment;
255
+
256
+    TERN_(HAS_EXTRUDERS, raw.e += extruder_per_segment);
244
 
257
 
245
     apply_motion_limits(raw);
258
     apply_motion_limits(raw);
246
 
259
 

+ 1
- 1
Marlin/src/gcode/motion/M290.cpp 查看文件

87
     }
87
     }
88
   #endif
88
   #endif
89
 
89
 
90
-  if (!parser.seen("XYZ") || parser.seen('R')) {
90
+  if (!parser.seen(LINEAR_AXIS_GANG("X", "Y", "Z")) || parser.seen('R')) {
91
     SERIAL_ECHO_START();
91
     SERIAL_ECHO_START();
92
 
92
 
93
     #if ENABLED(BABYSTEP_ZPROBE_OFFSET)
93
     #if ENABLED(BABYSTEP_ZPROBE_OFFSET)

+ 2
- 1
Marlin/src/gcode/parser.cpp 查看文件

248
         case 'R': if (!WITHIN(motion_mode_codenum, 2, 3)) return;
248
         case 'R': if (!WITHIN(motion_mode_codenum, 2, 3)) return;
249
       #endif
249
       #endif
250
 
250
 
251
-      case 'X' ... 'Z': case 'E' ... 'F':
251
+      LOGICAL_AXIS_GANG(case 'E':, case 'X':, case 'Y':, case 'Z':)
252
+      case 'F':
252
         if (motion_mode_codenum < 0) return;
253
         if (motion_mode_codenum < 0) return;
253
         command_letter = 'G';
254
         command_letter = 'G';
254
         codenum = motion_mode_codenum;
255
         codenum = motion_mode_codenum;

+ 1
- 1
Marlin/src/gcode/parser.h 查看文件

226
 
226
 
227
   // Seen any axis parameter
227
   // Seen any axis parameter
228
   static inline bool seen_axis() {
228
   static inline bool seen_axis() {
229
-    return seen("XYZE");
229
+    return seen(LOGICAL_AXIS_GANG("E", "X", "Y", "Z"));
230
   }
230
   }
231
 
231
 
232
   #if ENABLED(GCODE_QUOTED_STRINGS)
232
   #if ENABLED(GCODE_QUOTED_STRINGS)

+ 56
- 38
Marlin/src/inc/Conditionals_LCD.h 查看文件

537
  *  E_STEPPERS   - Number of actual E stepper motors
537
  *  E_STEPPERS   - Number of actual E stepper motors
538
  *  E_MANUAL     - Number of E steppers for LCD move options
538
  *  E_MANUAL     - Number of E steppers for LCD move options
539
  */
539
  */
540
-
541
 #if EXTRUDERS
540
 #if EXTRUDERS
542
   #define HAS_EXTRUDERS 1
541
   #define HAS_EXTRUDERS 1
543
   #if EXTRUDERS > 1
542
   #if EXTRUDERS > 1
544
     #define HAS_MULTI_EXTRUDER 1
543
     #define HAS_MULTI_EXTRUDER 1
545
   #endif
544
   #endif
545
+  #define E_AXIS_N(E) AxisEnum(E_AXIS + E_INDEX_N(E))
546
 #else
546
 #else
547
   #undef EXTRUDERS
547
   #undef EXTRUDERS
548
   #define EXTRUDERS 0
548
   #define EXTRUDERS 0
551
   #undef SWITCHING_NOZZLE
551
   #undef SWITCHING_NOZZLE
552
   #undef MIXING_EXTRUDER
552
   #undef MIXING_EXTRUDER
553
   #undef HOTEND_IDLE_TIMEOUT
553
   #undef HOTEND_IDLE_TIMEOUT
554
+  #undef DISABLE_E
554
 #endif
555
 #endif
555
 
556
 
556
 #if ENABLED(SWITCHING_EXTRUDER)   // One stepper for every two EXTRUDERS
557
 #if ENABLED(SWITCHING_EXTRUDER)   // One stepper for every two EXTRUDERS
604
   #define E_MANUAL EXTRUDERS
605
   #define E_MANUAL EXTRUDERS
605
 #endif
606
 #endif
606
 
607
 
608
+/**
609
+ * Number of Linear Axes (e.g., XYZ)
610
+ * All the logical axes except for the tool (E) axis
611
+ */
612
+#ifndef LINEAR_AXES
613
+  #define LINEAR_AXES XYZ
614
+#endif
615
+
616
+/**
617
+ * Number of Logical Axes (e.g., XYZE)
618
+ * All the logical axes that can be commanded directly by G-code.
619
+ * Delta maps stepper-specific values to ABC steppers.
620
+ */
621
+#if HAS_EXTRUDERS
622
+  #define LOGICAL_AXES INCREMENT(LINEAR_AXES)
623
+#else
624
+  #define LOGICAL_AXES LINEAR_AXES
625
+#endif
626
+
627
+/**
628
+ * DISTINCT_E_FACTORS is set to give extruders (some) individual settings.
629
+ *
630
+ * DISTINCT_AXES is the number of distinct addressable axes (not steppers).
631
+ *  Includes all linear axes plus all distinguished extruders.
632
+ *  The default behavior is to treat all extruders as a single E axis
633
+ *  with shared motion and temperature settings.
634
+ *
635
+ * DISTINCT_E is the number of distinguished extruders. By default this
636
+ *  well be 1 which indicates all extruders share the same settings.
637
+ *
638
+ * E_INDEX_N(E) should be used to get the E index of any item that might be
639
+ *  distinguished.
640
+ */
641
+#if ENABLED(DISTINCT_E_FACTORS) && E_STEPPERS > 1
642
+  #define DISTINCT_AXES (LINEAR_AXES + E_STEPPERS)
643
+  #define DISTINCT_E E_STEPPERS
644
+  #define E_INDEX_N(E) (E)
645
+#else
646
+  #undef DISTINCT_E_FACTORS
647
+  #define DISTINCT_AXES LOGICAL_AXES
648
+  #define DISTINCT_E 1
649
+  #define E_INDEX_N(E) 0
650
+#endif
651
+
607
 #if HOTENDS
652
 #if HOTENDS
608
   #define HAS_HOTEND 1
653
   #define HAS_HOTEND 1
609
   #ifndef HOTEND_OVERSHOOT
654
   #ifndef HOTEND_OVERSHOOT
624
 #define ARRAY_BY_HOTENDS(V...) ARRAY_N(HOTENDS, V)
669
 #define ARRAY_BY_HOTENDS(V...) ARRAY_N(HOTENDS, V)
625
 #define ARRAY_BY_HOTENDS1(v1) ARRAY_N_1(HOTENDS, v1)
670
 #define ARRAY_BY_HOTENDS1(v1) ARRAY_N_1(HOTENDS, v1)
626
 
671
 
627
-#if ENABLED(SWITCHING_EXTRUDER) && (DISABLED(SWITCHING_NOZZLE) || SWITCHING_EXTRUDER_SERVO_NR != SWITCHING_NOZZLE_SERVO_NR)
628
-  #define DO_SWITCH_EXTRUDER 1
629
-#endif
630
-
631
 /**
672
 /**
632
  * Default hotend offsets, if not defined
673
  * Default hotend offsets, if not defined
633
  */
674
  */
653
   #undef SINGLENOZZLE_STANDBY_FAN
694
   #undef SINGLENOZZLE_STANDBY_FAN
654
 #endif
695
 #endif
655
 
696
 
656
-/**
657
- * Number of Linear Axes (e.g., XYZ)
658
- * All the logical axes except for the tool (E) axis
659
- */
660
-#ifndef LINEAR_AXES
661
-  #define LINEAR_AXES XYZ
662
-#endif
663
-
664
-/**
665
- * Number of Logical Axes (e.g., XYZE)
666
- * All the logical axes that can be commanded directly by G-code.
667
- * Delta maps stepper-specific values to ABC steppers.
668
- */
669
-#if HAS_EXTRUDERS
670
-  #define LOGICAL_AXES INCREMENT(LINEAR_AXES)
671
-#else
672
-  #define LOGICAL_AXES LINEAR_AXES
673
-#endif
674
-
675
-/**
676
- * DISTINCT_E_FACTORS affects whether Extruders use different settings
677
- */
678
-#if ENABLED(DISTINCT_E_FACTORS) && E_STEPPERS > 1
679
-  #define DISTINCT_E E_STEPPERS
680
-  #define DISTINCT_AXES (LINEAR_AXES + E_STEPPERS)
681
-  #define E_INDEX_N(E) (E)
682
-#else
683
-  #undef DISTINCT_E_FACTORS
684
-  #define DISTINCT_E 1
685
-  #define DISTINCT_AXES LOGICAL_AXES
686
-  #define E_INDEX_N(E) 0
697
+// Switching extruder has its own servo?
698
+#if ENABLED(SWITCHING_EXTRUDER) && (DISABLED(SWITCHING_NOZZLE) || SWITCHING_EXTRUDER_SERVO_NR != SWITCHING_NOZZLE_SERVO_NR)
699
+  #define DO_SWITCH_EXTRUDER 1
687
 #endif
700
 #endif
688
-#define E_AXIS_N(E) AxisEnum(E_AXIS + E_INDEX_N(E))
689
 
701
 
690
 /**
702
 /**
691
  * The BLTouch Probe emulates a servo probe
703
  * The BLTouch Probe emulates a servo probe
726
   #define HAS_BED_PROBE 1
738
   #define HAS_BED_PROBE 1
727
 #endif
739
 #endif
728
 
740
 
741
+/**
742
+ * Fill in undefined Filament Sensor options
743
+ */
729
 #if ENABLED(FILAMENT_RUNOUT_SENSOR)
744
 #if ENABLED(FILAMENT_RUNOUT_SENSOR)
730
   #if NUM_RUNOUT_SENSORS >= 1
745
   #if NUM_RUNOUT_SENSORS >= 1
731
     #ifndef FIL_RUNOUT1_STATE
746
     #ifndef FIL_RUNOUT1_STATE
834
   #define Z_HOME_TO_MIN 1
849
   #define Z_HOME_TO_MIN 1
835
 #endif
850
 #endif
836
 
851
 
852
+/**
853
+ * Conditionals based on the type of Bed Probe
854
+ */
837
 #if HAS_BED_PROBE
855
 #if HAS_BED_PROBE
838
   #if DISABLED(NOZZLE_AS_PROBE)
856
   #if DISABLED(NOZZLE_AS_PROBE)
839
     #define HAS_PROBE_XY_OFFSET 1
857
     #define HAS_PROBE_XY_OFFSET 1
868
 #endif
886
 #endif
869
 
887
 
870
 /**
888
 /**
871
- * Set granular options based on the specific type of leveling
889
+ * Conditionals based on the type of Bed Leveling
872
  */
890
  */
873
 #if ENABLED(AUTO_BED_LEVELING_UBL)
891
 #if ENABLED(AUTO_BED_LEVELING_UBL)
874
   #undef LCD_BED_LEVELING
892
   #undef LCD_BED_LEVELING

+ 20
- 0
Marlin/src/inc/Conditionals_adv.h 查看文件

103
   #undef THERMAL_PROTECTION_PERIOD
103
   #undef THERMAL_PROTECTION_PERIOD
104
   #undef WATCH_TEMP_PERIOD
104
   #undef WATCH_TEMP_PERIOD
105
   #undef SHOW_TEMP_ADC_VALUES
105
   #undef SHOW_TEMP_ADC_VALUES
106
+  #undef LCD_SHOW_E_TOTAL
107
+  #undef MANUAL_E_MOVES_RELATIVE
108
+  #undef STEALTHCHOP_E
106
 #endif
109
 #endif
107
 
110
 
108
 #if TEMP_SENSOR_BED == 0
111
 #if TEMP_SENSOR_BED == 0
482
   #endif
485
   #endif
483
 #endif
486
 #endif
484
 
487
 
488
+// Remove unused STEALTHCHOP flags
489
+#if LINEAR_AXES < 6
490
+  #undef STEALTHCHOP_K
491
+  #if LINEAR_AXES < 5
492
+    #undef STEALTHCHOP_J
493
+    #if LINEAR_AXES < 4
494
+      #undef STEALTHCHOP_I
495
+      #if LINEAR_AXES < 3
496
+        #undef STEALTHCHOP_Z
497
+        #if LINEAR_AXES < 2
498
+          #undef STEALTHCHOP_Y
499
+        #endif
500
+      #endif
501
+    #endif
502
+  #endif
503
+#endif
504
+
485
 //
505
 //
486
 // SD Card connection methods
506
 // SD Card connection methods
487
 // Defined here so pins and sanity checks can use them
507
 // Defined here so pins and sanity checks can use them

+ 128
- 121
Marlin/src/inc/Conditionals_post.h 查看文件

1563
 #endif
1563
 #endif
1564
 
1564
 
1565
 // Extruder steppers and solenoids
1565
 // Extruder steppers and solenoids
1566
-#if PIN_EXISTS(E0_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E0))
1567
-  #define HAS_E0_ENABLE 1
1568
-#endif
1569
-#if PIN_EXISTS(E0_DIR)
1570
-  #define HAS_E0_DIR 1
1571
-#endif
1572
-#if PIN_EXISTS(E0_STEP)
1573
-  #define HAS_E0_STEP 1
1574
-#endif
1575
-#if PIN_EXISTS(E0_MS1)
1576
-  #define HAS_E0_MS_PINS 1
1577
-#endif
1578
-#if PIN_EXISTS(SOL0)
1579
-  #define HAS_SOLENOID_0 1
1580
-#endif
1566
+#if HAS_EXTRUDERS
1581
 
1567
 
1582
-#if PIN_EXISTS(E1_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E1))
1583
-  #define HAS_E1_ENABLE 1
1584
-#endif
1585
-#if PIN_EXISTS(E1_DIR)
1586
-  #define HAS_E1_DIR 1
1587
-#endif
1588
-#if PIN_EXISTS(E1_STEP)
1589
-  #define HAS_E1_STEP 1
1590
-#endif
1591
-#if PIN_EXISTS(E1_MS1)
1592
-  #define HAS_E1_MS_PINS 1
1593
-#endif
1594
-#if PIN_EXISTS(SOL1)
1595
-  #define HAS_SOLENOID_1 1
1596
-#endif
1568
+  #if PIN_EXISTS(E0_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E0))
1569
+    #define HAS_E0_ENABLE 1
1570
+  #endif
1571
+  #if PIN_EXISTS(E0_DIR)
1572
+    #define HAS_E0_DIR 1
1573
+  #endif
1574
+  #if PIN_EXISTS(E0_STEP)
1575
+    #define HAS_E0_STEP 1
1576
+  #endif
1577
+  #if PIN_EXISTS(E0_MS1)
1578
+    #define HAS_E0_MS_PINS 1
1579
+  #endif
1580
+  #if PIN_EXISTS(SOL0)
1581
+    #define HAS_SOLENOID_0 1
1582
+  #endif
1597
 
1583
 
1598
-#if PIN_EXISTS(E2_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E2))
1599
-  #define HAS_E2_ENABLE 1
1600
-#endif
1601
-#if PIN_EXISTS(E2_DIR)
1602
-  #define HAS_E2_DIR 1
1603
-#endif
1604
-#if PIN_EXISTS(E2_STEP)
1605
-  #define HAS_E2_STEP 1
1606
-#endif
1607
-#if PIN_EXISTS(E2_MS1)
1608
-  #define HAS_E2_MS_PINS 1
1609
-#endif
1610
-#if PIN_EXISTS(SOL2)
1611
-  #define HAS_SOLENOID_2 1
1612
-#endif
1584
+  #if PIN_EXISTS(E1_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E1))
1585
+    #define HAS_E1_ENABLE 1
1586
+  #endif
1587
+  #if PIN_EXISTS(E1_DIR)
1588
+    #define HAS_E1_DIR 1
1589
+  #endif
1590
+  #if PIN_EXISTS(E1_STEP)
1591
+    #define HAS_E1_STEP 1
1592
+  #endif
1593
+  #if PIN_EXISTS(E1_MS1)
1594
+    #define HAS_E1_MS_PINS 1
1595
+  #endif
1596
+  #if PIN_EXISTS(SOL1)
1597
+    #define HAS_SOLENOID_1 1
1598
+  #endif
1613
 
1599
 
1614
-#if PIN_EXISTS(E3_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E3))
1615
-  #define HAS_E3_ENABLE 1
1616
-#endif
1617
-#if PIN_EXISTS(E3_DIR)
1618
-  #define HAS_E3_DIR 1
1619
-#endif
1620
-#if PIN_EXISTS(E3_STEP)
1621
-  #define HAS_E3_STEP 1
1622
-#endif
1623
-#if PIN_EXISTS(E3_MS1)
1624
-  #define HAS_E3_MS_PINS 1
1625
-#endif
1626
-#if PIN_EXISTS(SOL3)
1627
-  #define HAS_SOLENOID_3 1
1628
-#endif
1600
+  #if PIN_EXISTS(E2_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E2))
1601
+    #define HAS_E2_ENABLE 1
1602
+  #endif
1603
+  #if PIN_EXISTS(E2_DIR)
1604
+    #define HAS_E2_DIR 1
1605
+  #endif
1606
+  #if PIN_EXISTS(E2_STEP)
1607
+    #define HAS_E2_STEP 1
1608
+  #endif
1609
+  #if PIN_EXISTS(E2_MS1)
1610
+    #define HAS_E2_MS_PINS 1
1611
+  #endif
1612
+  #if PIN_EXISTS(SOL2)
1613
+    #define HAS_SOLENOID_2 1
1614
+  #endif
1629
 
1615
 
1630
-#if PIN_EXISTS(E4_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E4))
1631
-  #define HAS_E4_ENABLE 1
1632
-#endif
1633
-#if PIN_EXISTS(E4_DIR)
1634
-  #define HAS_E4_DIR 1
1635
-#endif
1636
-#if PIN_EXISTS(E4_STEP)
1637
-  #define HAS_E4_STEP 1
1638
-#endif
1639
-#if PIN_EXISTS(E4_MS1)
1640
-  #define HAS_E4_MS_PINS 1
1641
-#endif
1642
-#if PIN_EXISTS(SOL4)
1643
-  #define HAS_SOLENOID_4 1
1644
-#endif
1616
+  #if PIN_EXISTS(E3_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E3))
1617
+    #define HAS_E3_ENABLE 1
1618
+  #endif
1619
+  #if PIN_EXISTS(E3_DIR)
1620
+    #define HAS_E3_DIR 1
1621
+  #endif
1622
+  #if PIN_EXISTS(E3_STEP)
1623
+    #define HAS_E3_STEP 1
1624
+  #endif
1625
+  #if PIN_EXISTS(E3_MS1)
1626
+    #define HAS_E3_MS_PINS 1
1627
+  #endif
1628
+  #if PIN_EXISTS(SOL3)
1629
+    #define HAS_SOLENOID_3 1
1630
+  #endif
1645
 
1631
 
1646
-#if PIN_EXISTS(E5_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E5))
1647
-  #define HAS_E5_ENABLE 1
1648
-#endif
1649
-#if PIN_EXISTS(E5_DIR)
1650
-  #define HAS_E5_DIR 1
1651
-#endif
1652
-#if PIN_EXISTS(E5_STEP)
1653
-  #define HAS_E5_STEP 1
1654
-#endif
1655
-#if PIN_EXISTS(E5_MS1)
1656
-  #define HAS_E5_MS_PINS 1
1657
-#endif
1658
-#if PIN_EXISTS(SOL5)
1659
-  #define HAS_SOLENOID_5 1
1660
-#endif
1632
+  #if PIN_EXISTS(E4_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E4))
1633
+    #define HAS_E4_ENABLE 1
1634
+  #endif
1635
+  #if PIN_EXISTS(E4_DIR)
1636
+    #define HAS_E4_DIR 1
1637
+  #endif
1638
+  #if PIN_EXISTS(E4_STEP)
1639
+    #define HAS_E4_STEP 1
1640
+  #endif
1641
+  #if PIN_EXISTS(E4_MS1)
1642
+    #define HAS_E4_MS_PINS 1
1643
+  #endif
1644
+  #if PIN_EXISTS(SOL4)
1645
+    #define HAS_SOLENOID_4 1
1646
+  #endif
1661
 
1647
 
1662
-#if PIN_EXISTS(E6_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E6))
1663
-  #define HAS_E6_ENABLE 1
1664
-#endif
1665
-#if PIN_EXISTS(E6_DIR)
1666
-  #define HAS_E6_DIR 1
1667
-#endif
1668
-#if PIN_EXISTS(E6_STEP)
1669
-  #define HAS_E6_STEP 1
1670
-#endif
1671
-#if PIN_EXISTS(E6_MS1)
1672
-  #define HAS_E6_MS_PINS 1
1673
-#endif
1674
-#if PIN_EXISTS(SOL6)
1675
-  #define HAS_SOLENOID_6 1
1676
-#endif
1648
+  #if PIN_EXISTS(E5_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E5))
1649
+    #define HAS_E5_ENABLE 1
1650
+  #endif
1651
+  #if PIN_EXISTS(E5_DIR)
1652
+    #define HAS_E5_DIR 1
1653
+  #endif
1654
+  #if PIN_EXISTS(E5_STEP)
1655
+    #define HAS_E5_STEP 1
1656
+  #endif
1657
+  #if PIN_EXISTS(E5_MS1)
1658
+    #define HAS_E5_MS_PINS 1
1659
+  #endif
1660
+  #if PIN_EXISTS(SOL5)
1661
+    #define HAS_SOLENOID_5 1
1662
+  #endif
1677
 
1663
 
1678
-#if PIN_EXISTS(E7_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E7))
1679
-  #define HAS_E7_ENABLE 1
1680
-#endif
1681
-#if PIN_EXISTS(E7_DIR)
1682
-  #define HAS_E7_DIR 1
1683
-#endif
1684
-#if PIN_EXISTS(E7_STEP)
1685
-  #define HAS_E7_STEP 1
1686
-#endif
1687
-#if PIN_EXISTS(E7_MS1)
1688
-  #define HAS_E7_MS_PINS 1
1689
-#endif
1690
-#if PIN_EXISTS(SOL7)
1691
-  #define HAS_SOLENOID_7 1
1692
-#endif
1664
+  #if PIN_EXISTS(E6_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E6))
1665
+    #define HAS_E6_ENABLE 1
1666
+  #endif
1667
+  #if PIN_EXISTS(E6_DIR)
1668
+    #define HAS_E6_DIR 1
1669
+  #endif
1670
+  #if PIN_EXISTS(E6_STEP)
1671
+    #define HAS_E6_STEP 1
1672
+  #endif
1673
+  #if PIN_EXISTS(E6_MS1)
1674
+    #define HAS_E6_MS_PINS 1
1675
+  #endif
1676
+  #if PIN_EXISTS(SOL6)
1677
+    #define HAS_SOLENOID_6 1
1678
+  #endif
1679
+
1680
+  #if PIN_EXISTS(E7_ENABLE) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(E7))
1681
+    #define HAS_E7_ENABLE 1
1682
+  #endif
1683
+  #if PIN_EXISTS(E7_DIR)
1684
+    #define HAS_E7_DIR 1
1685
+  #endif
1686
+  #if PIN_EXISTS(E7_STEP)
1687
+    #define HAS_E7_STEP 1
1688
+  #endif
1689
+  #if PIN_EXISTS(E7_MS1)
1690
+    #define HAS_E7_MS_PINS 1
1691
+  #endif
1692
+  #if PIN_EXISTS(SOL7)
1693
+    #define HAS_SOLENOID_7 1
1694
+  #endif
1695
+
1696
+#endif // HAS_EXTRUDERS
1693
 
1697
 
1694
 //
1698
 //
1695
 // Trinamic Stepper Drivers
1699
 // Trinamic Stepper Drivers
2348
 #if PIN_EXISTS(DIGIPOTSS)
2352
 #if PIN_EXISTS(DIGIPOTSS)
2349
   #define HAS_MOTOR_CURRENT_SPI 1
2353
   #define HAS_MOTOR_CURRENT_SPI 1
2350
 #endif
2354
 #endif
2351
-#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_Z, MOTOR_CURRENT_PWM_E)
2355
+#if HAS_EXTRUDERS && PIN_EXISTS(MOTOR_CURRENT_PWM_E)
2356
+  #define HAS_MOTOR_CURRENT_PWM_E 1
2357
+#endif
2358
+#if HAS_MOTOR_CURRENT_PWM_E || ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_Z)
2352
   #define HAS_MOTOR_CURRENT_PWM 1
2359
   #define HAS_MOTOR_CURRENT_PWM 1
2353
 #endif
2360
 #endif
2354
 
2361
 

+ 16
- 11
Marlin/src/inc/SanityCheck.h 查看文件

1593
  * Homing
1593
  * Homing
1594
  */
1594
  */
1595
 constexpr float hbm[] = HOMING_BUMP_MM;
1595
 constexpr float hbm[] = HOMING_BUMP_MM;
1596
-static_assert(COUNT(hbm) == XYZ, "HOMING_BUMP_MM requires X, Y, and Z elements.");
1597
-static_assert(hbm[X_AXIS] >= 0, "HOMING_BUMP_MM.X must be greater than or equal to 0.");
1598
-static_assert(hbm[Y_AXIS] >= 0, "HOMING_BUMP_MM.Y must be greater than or equal to 0.");
1599
-static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal to 0.");
1600
-
1596
+static_assert(COUNT(hbm) == LINEAR_AXES, "HOMING_BUMP_MM requires one element per linear axis.");
1597
+LINEAR_AXIS_CODE(
1598
+  static_assert(hbm[X_AXIS] >= 0, "HOMING_BUMP_MM.X must be greater than or equal to 0."),
1599
+  static_assert(hbm[Y_AXIS] >= 0, "HOMING_BUMP_MM.Y must be greater than or equal to 0."),
1600
+  static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal to 0.")
1601
+);
1601
 #if ENABLED(CODEPENDENT_XY_HOMING)
1602
 #if ENABLED(CODEPENDENT_XY_HOMING)
1602
   #if ENABLED(QUICK_HOME)
1603
   #if ENABLED(QUICK_HOME)
1603
     #error "QUICK_HOME is incompatible with CODEPENDENT_XY_HOMING."
1604
     #error "QUICK_HOME is incompatible with CODEPENDENT_XY_HOMING."
1976
   #error "HEATER_0_PIN not defined for this board."
1977
   #error "HEATER_0_PIN not defined for this board."
1977
 #elif !ANY_PIN(TEMP_0, MAX6675_SS)
1978
 #elif !ANY_PIN(TEMP_0, MAX6675_SS)
1978
   #error "TEMP_0_PIN or MAX6675_SS not defined for this board."
1979
   #error "TEMP_0_PIN or MAX6675_SS not defined for this board."
1979
-#elif ((defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)) && !PINS_EXIST(E0_STEP, E0_DIR))
1980
-  #error "E0_STEP_PIN or E0_DIR_PIN not defined for this board."
1981
-#elif ( !(defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)) && (!PINS_EXIST(E0_STEP, E0_DIR) || !HAS_E0_ENABLE))
1982
-  #error "E0_STEP_PIN, E0_DIR_PIN, or E0_ENABLE_PIN not defined for this board."
1983
-#elif EXTRUDERS && TEMP_SENSOR_0 == 0
1984
-  #error "TEMP_SENSOR_0 is required if there are any extruders."
1980
+#endif
1981
+
1982
+#if HAS_EXTRUDERS
1983
+  #if ((defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)) && !PINS_EXIST(E0_STEP, E0_DIR))
1984
+    #error "E0_STEP_PIN or E0_DIR_PIN not defined for this board."
1985
+  #elif ( !(defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)) && (!PINS_EXIST(E0_STEP, E0_DIR) || !HAS_E0_ENABLE))
1986
+    #error "E0_STEP_PIN, E0_DIR_PIN, or E0_ENABLE_PIN not defined for this board."
1987
+  #elif EXTRUDERS && TEMP_SENSOR_0 == 0
1988
+    #error "TEMP_SENSOR_0 is required if there are any extruders."
1989
+  #endif
1985
 #endif
1990
 #endif
1986
 
1991
 
1987
 /**
1992
 /**

+ 4
- 2
Marlin/src/lcd/dogm/status_screen_DOGM.cpp 查看文件

856
       #else
856
       #else
857
 
857
 
858
         if (show_e_total) {
858
         if (show_e_total) {
859
-          _draw_axis_value(E_AXIS, xstring, true);
860
-          lcd_put_u8str_P(PSTR("       "));
859
+          #if ENABLED(LCD_SHOW_E_TOTAL)
860
+            _draw_axis_value(E_AXIS, xstring, true);
861
+            lcd_put_u8str_P(PSTR("       "));
862
+          #endif
861
         }
863
         }
862
         else {
864
         else {
863
           _draw_axis_value(X_AXIS, xstring, blink);
865
           _draw_axis_value(X_AXIS, xstring, blink);

+ 4
- 4
Marlin/src/lcd/extui/dgus/mks/DGUSDisplayDef.cpp 查看文件

666
   VPHELPER(VP_Z_MAX_SPEED, &planner.settings.max_feedrate_mm_s[Z_AXIS], ScreenHandler.HandleMaxSpeedChange_MKS, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<0>),
666
   VPHELPER(VP_Z_MAX_SPEED, &planner.settings.max_feedrate_mm_s[Z_AXIS], ScreenHandler.HandleMaxSpeedChange_MKS, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<0>),
667
 
667
 
668
   #if HOTENDS >= 1
668
   #if HOTENDS >= 1
669
-    VPHELPER(VP_E0_MAX_SPEED, &planner.settings.max_feedrate_mm_s[E0_AXIS], ScreenHandler.HandleExtruderMaxSpeedChange_MKS, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<0>),
669
+    VPHELPER(VP_E0_MAX_SPEED, &planner.settings.max_feedrate_mm_s[E_AXIS_N(0)], ScreenHandler.HandleExtruderMaxSpeedChange_MKS, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<0>),
670
   #endif
670
   #endif
671
   #if HOTENDS >= 2
671
   #if HOTENDS >= 2
672
-    VPHELPER(VP_E1_MAX_SPEED, &planner.settings.max_feedrate_mm_s[E1_AXIS], ScreenHandler.HandleExtruderMaxSpeedChange_MKS, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<0>),
672
+    VPHELPER(VP_E1_MAX_SPEED, &planner.settings.max_feedrate_mm_s[E_AXIS_N(1)], ScreenHandler.HandleExtruderMaxSpeedChange_MKS, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<0>),
673
   #endif
673
   #endif
674
 
674
 
675
   VPHELPER(VP_X_ACC_MAX_SPEED, (uint16_t *)&planner.settings.max_acceleration_mm_per_s2[X_AXIS], ScreenHandler.HandleMaxAccChange_MKS, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
675
   VPHELPER(VP_X_ACC_MAX_SPEED, (uint16_t *)&planner.settings.max_acceleration_mm_per_s2[X_AXIS], ScreenHandler.HandleMaxAccChange_MKS, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
677
   VPHELPER(VP_Z_ACC_MAX_SPEED, (uint16_t *)&planner.settings.max_acceleration_mm_per_s2[Z_AXIS], ScreenHandler.HandleMaxAccChange_MKS, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
677
   VPHELPER(VP_Z_ACC_MAX_SPEED, (uint16_t *)&planner.settings.max_acceleration_mm_per_s2[Z_AXIS], ScreenHandler.HandleMaxAccChange_MKS, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
678
 
678
 
679
   #if HOTENDS >= 1
679
   #if HOTENDS >= 1
680
-    VPHELPER(VP_E0_ACC_MAX_SPEED, (uint16_t *)&planner.settings.max_acceleration_mm_per_s2[E0_AXIS], ScreenHandler.HandleExtruderAccChange_MKS, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
680
+    VPHELPER(VP_E0_ACC_MAX_SPEED, (uint16_t *)&planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(0)], ScreenHandler.HandleExtruderAccChange_MKS, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
681
   #endif
681
   #endif
682
   #if HOTENDS >= 2
682
   #if HOTENDS >= 2
683
-    VPHELPER(VP_E1_ACC_MAX_SPEED, (uint16_t *)&planner.settings.max_acceleration_mm_per_s2[E1_AXIS], ScreenHandler.HandleExtruderAccChange_MKS, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
683
+    VPHELPER(VP_E1_ACC_MAX_SPEED, (uint16_t *)&planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(1)], ScreenHandler.HandleExtruderAccChange_MKS, ScreenHandler.DGUSLCD_SendWordValueToDisplay),
684
   #endif
684
   #endif
685
 
685
 
686
   VPHELPER(VP_TRAVEL_SPEED, (uint16_t *)&planner.settings.travel_acceleration, ScreenHandler.HandleTravelAccChange_MKS, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<0>),
686
   VPHELPER(VP_TRAVEL_SPEED, (uint16_t *)&planner.settings.travel_acceleration, ScreenHandler.HandleTravelAccChange_MKS, ScreenHandler.DGUSLCD_SendFloatAsIntValueToDisplay<0>),

+ 7
- 3
Marlin/src/lcd/marlinui.cpp 查看文件

712
     // Add a manual move to the queue?
712
     // Add a manual move to the queue?
713
     if (axis != NO_AXIS_ENUM && ELAPSED(millis(), start_time) && !planner.is_full()) {
713
     if (axis != NO_AXIS_ENUM && ELAPSED(millis(), start_time) && !planner.is_full()) {
714
 
714
 
715
-      const feedRate_t fr_mm_s = (axis <= E_AXIS) ? manual_feedrate_mm_s[axis] : XY_PROBE_FEEDRATE_MM_S;
715
+      const feedRate_t fr_mm_s = (axis <= LOGICAL_AXES) ? manual_feedrate_mm_s[axis] : XY_PROBE_FEEDRATE_MM_S;
716
 
716
 
717
       #if IS_KINEMATIC
717
       #if IS_KINEMATIC
718
 
718
 
719
         #if HAS_MULTI_EXTRUDER
719
         #if HAS_MULTI_EXTRUDER
720
           REMEMBER(ae, active_extruder);
720
           REMEMBER(ae, active_extruder);
721
-          if (axis == E_AXIS) active_extruder = e_index;
721
+          #if MULTI_E_MANUAL
722
+            if (axis == E_AXIS) active_extruder = e_index;
723
+          #endif
722
         #endif
724
         #endif
723
 
725
 
724
         // Apply a linear offset to a single axis
726
         // Apply a linear offset to a single axis
744
       #else
746
       #else
745
 
747
 
746
         // For Cartesian / Core motion simply move to the current_position
748
         // For Cartesian / Core motion simply move to the current_position
747
-        planner.buffer_line(current_position, fr_mm_s, axis == E_AXIS ? e_index : active_extruder);
749
+        planner.buffer_line(current_position, fr_mm_s,
750
+          TERN_(MULTI_E_MANUAL, axis == E_AXIS ? e_index :) active_extruder
751
+        );
748
 
752
 
749
         //SERIAL_ECHOLNPAIR("Add planner.move with Axis ", AS_CHAR(axis_codes[axis]), " at FR ", fr_mm_s);
753
         //SERIAL_ECHOLNPAIR("Add planner.move with Axis ", AS_CHAR(axis_codes[axis]), " at FR ", fr_mm_s);
750
 
754
 

+ 18
- 22
Marlin/src/lcd/menu/menu_advanced.cpp 查看文件

68
     START_MENU();
68
     START_MENU();
69
     BACK_ITEM(MSG_ADVANCED_SETTINGS);
69
     BACK_ITEM(MSG_ADVANCED_SETTINGS);
70
     #define EDIT_DAC_PERCENT(A) EDIT_ITEM(uint8, MSG_DAC_PERCENT_##A, &driverPercent[_AXIS(A)], 0, 100, []{ stepper_dac.set_current_percents(driverPercent); })
70
     #define EDIT_DAC_PERCENT(A) EDIT_ITEM(uint8, MSG_DAC_PERCENT_##A, &driverPercent[_AXIS(A)], 0, 100, []{ stepper_dac.set_current_percents(driverPercent); })
71
-    EDIT_DAC_PERCENT(X);
72
-    EDIT_DAC_PERCENT(Y);
73
-    EDIT_DAC_PERCENT(Z);
74
-    EDIT_DAC_PERCENT(E);
71
+    LOGICAL_AXIS_CODE(EDIT_DAC_PERCENT(E), EDIT_DAC_PERCENT(X), EDIT_DAC_PERCENT(Y), EDIT_DAC_PERCENT(Z), EDIT_DAC_PERCENT(I), EDIT_DAC_PERCENT(J), EDIT_DAC_PERCENT(K));
75
     ACTION_ITEM(MSG_DAC_EEPROM_WRITE, stepper_dac.commit_eeprom);
72
     ACTION_ITEM(MSG_DAC_EEPROM_WRITE, stepper_dac.commit_eeprom);
76
     END_MENU();
73
     END_MENU();
77
   }
74
   }
359
       #elif ENABLED(LIMITED_MAX_FR_EDITING)
356
       #elif ENABLED(LIMITED_MAX_FR_EDITING)
360
         DEFAULT_MAX_FEEDRATE
357
         DEFAULT_MAX_FEEDRATE
361
       #else
358
       #else
362
-        { 9999, 9999, 9999, 9999 }
359
+        LOGICAL_AXIS_ARRAY(9999, 9999, 9999, 9999)
363
       #endif
360
       #endif
364
     ;
361
     ;
365
     #if ENABLED(LIMITED_MAX_FR_EDITING) && !defined(MAX_FEEDRATE_EDIT_VALUES)
362
     #if ENABLED(LIMITED_MAX_FR_EDITING) && !defined(MAX_FEEDRATE_EDIT_VALUES)
372
     BACK_ITEM(MSG_ADVANCED_SETTINGS);
369
     BACK_ITEM(MSG_ADVANCED_SETTINGS);
373
 
370
 
374
     #define EDIT_VMAX(N) EDIT_ITEM_FAST(float5, MSG_VMAX_##N, &planner.settings.max_feedrate_mm_s[_AXIS(N)], 1, max_fr_edit_scaled[_AXIS(N)])
371
     #define EDIT_VMAX(N) EDIT_ITEM_FAST(float5, MSG_VMAX_##N, &planner.settings.max_feedrate_mm_s[_AXIS(N)], 1, max_fr_edit_scaled[_AXIS(N)])
375
-    EDIT_VMAX(A);
376
-    EDIT_VMAX(B);
377
-    EDIT_VMAX(C);
372
+    LINEAR_AXIS_CODE(EDIT_VMAX(A), EDIT_VMAX(B), EDIT_VMAX(C), EDIT_VMAX(I), EDIT_VMAX(J), EDIT_VMAX(K));
378
 
373
 
379
     #if E_STEPPERS
374
     #if E_STEPPERS
380
       EDIT_ITEM_FAST(float5, MSG_VMAX_E, &planner.settings.max_feedrate_mm_s[E_AXIS_N(active_extruder)], 1, max_fr_edit_scaled.e);
375
       EDIT_ITEM_FAST(float5, MSG_VMAX_E, &planner.settings.max_feedrate_mm_s[E_AXIS_N(active_extruder)], 1, max_fr_edit_scaled.e);
404
       #elif ENABLED(LIMITED_MAX_ACCEL_EDITING)
399
       #elif ENABLED(LIMITED_MAX_ACCEL_EDITING)
405
         DEFAULT_MAX_ACCELERATION
400
         DEFAULT_MAX_ACCELERATION
406
       #else
401
       #else
407
-        { 99000, 99000, 99000, 99000 }
402
+        LOGICAL_AXIS_ARRAY(99000, 99000, 99000, 99000)
408
       #endif
403
       #endif
409
     ;
404
     ;
410
     #if ENABLED(LIMITED_MAX_ACCEL_EDITING) && !defined(MAX_ACCEL_EDIT_VALUES)
405
     #if ENABLED(LIMITED_MAX_ACCEL_EDITING) && !defined(MAX_ACCEL_EDIT_VALUES)
419
     // M204 P Acceleration
414
     // M204 P Acceleration
420
     EDIT_ITEM_FAST(float5_25, MSG_ACC, &planner.settings.acceleration, 25, max_accel);
415
     EDIT_ITEM_FAST(float5_25, MSG_ACC, &planner.settings.acceleration, 25, max_accel);
421
 
416
 
422
-    // M204 R Retract Acceleration
423
-    EDIT_ITEM_FAST(float5, MSG_A_RETRACT, &planner.settings.retract_acceleration, 100, planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)]);
417
+    #if HAS_EXTRUDERS
418
+      // M204 R Retract Acceleration
419
+      EDIT_ITEM_FAST(float5, MSG_A_RETRACT, &planner.settings.retract_acceleration, 100, planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)]);
420
+    #endif
424
 
421
 
425
     // M204 T Travel Acceleration
422
     // M204 T Travel Acceleration
426
     EDIT_ITEM_FAST(float5_25, MSG_A_TRAVEL, &planner.settings.travel_acceleration, 25, max_accel);
423
     EDIT_ITEM_FAST(float5_25, MSG_A_TRAVEL, &planner.settings.travel_acceleration, 25, max_accel);
427
 
424
 
428
     #define EDIT_AMAX(Q,L) EDIT_ITEM_FAST(long5_25, MSG_AMAX_##Q, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.reset_acceleration_rates(); })
425
     #define EDIT_AMAX(Q,L) EDIT_ITEM_FAST(long5_25, MSG_AMAX_##Q, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.reset_acceleration_rates(); })
429
-    EDIT_AMAX(A, 100);
430
-    EDIT_AMAX(B, 100);
431
-    EDIT_AMAX(C,  10);
426
+    LINEAR_AXIS_CODE(
427
+      EDIT_AMAX(A, 100), EDIT_AMAX(B, 100), EDIT_AMAX(C, 10),
428
+      EDIT_AMAX(I,  10), EDIT_AMAX(J,  10), EDIT_AMAX(K, 10)
429
+    );
432
 
430
 
433
     #if ENABLED(DISTINCT_E_FACTORS)
431
     #if ENABLED(DISTINCT_E_FACTORS)
434
       EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)], 100, max_accel_edit_scaled.e, []{ planner.reset_acceleration_rates(); });
432
       EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)], 100, max_accel_edit_scaled.e, []{ planner.reset_acceleration_rates(); });
474
         #endif
472
         #endif
475
       ;
473
       ;
476
       #define EDIT_JERK(N) EDIT_ITEM_FAST(float3, MSG_V##N##_JERK, &planner.max_jerk[_AXIS(N)], 1, max_jerk_edit[_AXIS(N)])
474
       #define EDIT_JERK(N) EDIT_ITEM_FAST(float3, MSG_V##N##_JERK, &planner.max_jerk[_AXIS(N)], 1, max_jerk_edit[_AXIS(N)])
477
-      EDIT_JERK(A);
478
-      EDIT_JERK(B);
479
       #if ENABLED(DELTA)
475
       #if ENABLED(DELTA)
480
-        EDIT_JERK(C);
476
+        #define EDIT_JERK_C() EDIT_JERK(C)
481
       #else
477
       #else
482
-        EDIT_ITEM_FAST(float52sign, MSG_VC_JERK, &planner.max_jerk.c, 0.1f, max_jerk_edit.c);
478
+        #define EDIT_JERK_C() EDIT_ITEM_FAST(float52sign, MSG_VC_JERK, &planner.max_jerk.c, 0.1f, max_jerk_edit.c)
483
       #endif
479
       #endif
484
-      #if HAS_CLASSIC_E_JERK
480
+      LINEAR_AXIS_CODE(EDIT_JERK(A), EDIT_JERK(B), EDIT_JERK_C());
481
+
482
+      #if HAS_EXTRUDERS
485
         EDIT_ITEM_FAST(float52sign, MSG_VE_JERK, &planner.max_jerk.e, 0.1f, max_jerk_edit.e);
483
         EDIT_ITEM_FAST(float52sign, MSG_VE_JERK, &planner.max_jerk.e, 0.1f, max_jerk_edit.e);
486
       #endif
484
       #endif
487
 
485
 
517
   BACK_ITEM(MSG_ADVANCED_SETTINGS);
515
   BACK_ITEM(MSG_ADVANCED_SETTINGS);
518
 
516
 
519
   #define EDIT_QSTEPS(Q) EDIT_ITEM_FAST(float51, MSG_##Q##_STEPS, &planner.settings.axis_steps_per_mm[_AXIS(Q)], 5, 9999, []{ planner.refresh_positioning(); })
517
   #define EDIT_QSTEPS(Q) EDIT_ITEM_FAST(float51, MSG_##Q##_STEPS, &planner.settings.axis_steps_per_mm[_AXIS(Q)], 5, 9999, []{ planner.refresh_positioning(); })
520
-  EDIT_QSTEPS(A);
521
-  EDIT_QSTEPS(B);
522
-  EDIT_QSTEPS(C);
518
+  LINEAR_AXIS_CODE(EDIT_QSTEPS(A), EDIT_QSTEPS(B), EDIT_QSTEPS(C));
523
 
519
 
524
   #if ENABLED(DISTINCT_E_FACTORS)
520
   #if ENABLED(DISTINCT_E_FACTORS)
525
     LOOP_L_N(n, E_STEPPERS)
521
     LOOP_L_N(n, E_STEPPERS)

+ 9
- 2
Marlin/src/module/endstops.cpp 查看文件

361
   prev_hit_state = hit_state;
361
   prev_hit_state = hit_state;
362
   if (hit_state) {
362
   if (hit_state) {
363
     #if HAS_STATUS_MESSAGE
363
     #if HAS_STATUS_MESSAGE
364
-      char chrX = ' ', chrY = ' ', chrZ = ' ', chrP = ' ';
364
+      char LINEAR_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' '),
365
+           chrP = ' ';
365
       #define _SET_STOP_CHAR(A,C) (chr## A = C)
366
       #define _SET_STOP_CHAR(A,C) (chr## A = C)
366
     #else
367
     #else
367
       #define _SET_STOP_CHAR(A,C) NOOP
368
       #define _SET_STOP_CHAR(A,C) NOOP
390
     #endif
391
     #endif
391
     SERIAL_EOL();
392
     SERIAL_EOL();
392
 
393
 
393
-    TERN_(HAS_STATUS_MESSAGE, ui.status_printf_P(0, PSTR(S_FMT " %c %c %c %c"), GET_TEXT(MSG_LCD_ENDSTOPS), chrX, chrY, chrZ, chrP));
394
+    TERN_(HAS_STATUS_MESSAGE,
395
+      ui.status_printf_P(0,
396
+        PSTR(S_FMT GANG_N_1(LINEAR_AXES, " %c") " %c"),
397
+        GET_TEXT(MSG_LCD_ENDSTOPS),
398
+        LINEAR_AXIS_LIST(chrX, chrY, chrZ), chrP
399
+      )
400
+    );
394
 
401
 
395
     #if BOTH(SD_ABORT_ON_ENDSTOP_HIT, SDSUPPORT)
402
     #if BOTH(SD_ABORT_ON_ENDSTOP_HIT, SDSUPPORT)
396
       if (planner.abort_on_endstop_hit) {
403
       if (planner.abort_on_endstop_hit) {

+ 68
- 34
Marlin/src/module/motion.cpp 查看文件

89
   #define Z_INIT_POS Z_HOME_POS
89
   #define Z_INIT_POS Z_HOME_POS
90
 #endif
90
 #endif
91
 
91
 
92
-xyze_pos_t current_position = { X_HOME_POS, Y_HOME_POS, Z_INIT_POS };
92
+xyze_pos_t current_position = LOGICAL_AXIS_ARRAY(0, X_HOME_POS, Y_HOME_POS, Z_INIT_POS);
93
 
93
 
94
 /**
94
 /**
95
  * Cartesian Destination
95
  * Cartesian Destination
195
 // Report the logical position for a given machine position
195
 // Report the logical position for a given machine position
196
 inline void report_logical_position(const xyze_pos_t &rpos) {
196
 inline void report_logical_position(const xyze_pos_t &rpos) {
197
   const xyze_pos_t lpos = rpos.asLogical();
197
   const xyze_pos_t lpos = rpos.asLogical();
198
-  SERIAL_ECHOPAIR_P(X_LBL, lpos.x, SP_Y_LBL, lpos.y, SP_Z_LBL, lpos.z, SP_E_LBL, lpos.e);
198
+  SERIAL_ECHOPAIR_P(
199
+    LIST_N(DOUBLE(LINEAR_AXES), X_LBL, lpos.x, SP_Y_LBL, lpos.y, SP_Z_LBL, lpos.z)
200
+    #if HAS_EXTRUDERS
201
+      , SP_E_LBL, lpos.e
202
+    #endif
203
+  );
199
 }
204
 }
200
 
205
 
201
 // Report the real current position according to the steppers.
206
 // Report the real current position according to the steppers.
202
 // Forward kinematics and un-leveling are applied.
207
 // Forward kinematics and un-leveling are applied.
203
 void report_real_position() {
208
 void report_real_position() {
204
   get_cartesian_from_steppers();
209
   get_cartesian_from_steppers();
205
-  xyze_pos_t npos = cartes;
206
-  npos.e = planner.get_axis_position_mm(E_AXIS);
210
+  xyze_pos_t npos = LOGICAL_AXIS_ARRAY(
211
+    planner.get_axis_position_mm(E_AXIS),
212
+    cartes.x, cartes.y, cartes.z
213
+  );
214
+
207
   TERN_(HAS_POSITION_MODIFIERS, planner.unapply_modifiers(npos, true));
215
   TERN_(HAS_POSITION_MODIFIERS, planner.unapply_modifiers(npos, true));
216
+
208
   report_logical_position(npos);
217
   report_logical_position(npos);
209
   report_more_positions();
218
   report_more_positions();
210
 }
219
 }
309
   planner.set_position_mm(current_position);
318
   planner.set_position_mm(current_position);
310
 }
319
 }
311
 
320
 
312
-void sync_plan_position_e() { planner.set_e_position_mm(current_position.e); }
321
+#if HAS_EXTRUDERS
322
+  void sync_plan_position_e() { planner.set_e_position_mm(current_position.e); }
323
+#endif
313
 
324
 
314
 /**
325
 /**
315
  * Get the stepper positions in the cartes[] array.
326
  * Get the stepper positions in the cartes[] array.
354
 void set_current_from_steppers_for_axis(const AxisEnum axis) {
365
 void set_current_from_steppers_for_axis(const AxisEnum axis) {
355
   get_cartesian_from_steppers();
366
   get_cartesian_from_steppers();
356
   xyze_pos_t pos = cartes;
367
   xyze_pos_t pos = cartes;
357
-  pos.e = planner.get_axis_position_mm(E_AXIS);
368
+
369
+  #if HAS_EXTRUDERS
370
+    pos.e = planner.get_axis_position_mm(E_AXIS);
371
+  #endif
358
 
372
 
359
   #if HAS_POSITION_MODIFIERS
373
   #if HAS_POSITION_MODIFIERS
360
     planner.unapply_modifiers(pos, true);
374
     planner.unapply_modifiers(pos, true);
442
  * - Delta may lower Z first to get into the free motion zone.
456
  * - Delta may lower Z first to get into the free motion zone.
443
  * - Before returning, wait for the planner buffer to empty.
457
  * - Before returning, wait for the planner buffer to empty.
444
  */
458
  */
445
-void do_blocking_move_to(const float rx, const float ry, const float rz, const_feedRate_t fr_mm_s/*=0.0*/) {
459
+void do_blocking_move_to(
460
+  LINEAR_AXIS_LIST(const float rx, const float ry, const float rz),
461
+  const_feedRate_t fr_mm_s/*=0.0f*/
462
+) {
446
   DEBUG_SECTION(log_move, "do_blocking_move_to", DEBUGGING(LEVELING));
463
   DEBUG_SECTION(log_move, "do_blocking_move_to", DEBUGGING(LEVELING));
447
-  if (DEBUGGING(LEVELING)) DEBUG_XYZ("> ", rx, ry, rz);
464
+  if (DEBUGGING(LEVELING)) DEBUG_XYZ("> ", LINEAR_AXIS_LIST(rx, ry, rz));
448
 
465
 
449
   const feedRate_t z_feedrate = fr_mm_s ?: homing_feedrate(Z_AXIS),
466
   const feedRate_t z_feedrate = fr_mm_s ?: homing_feedrate(Z_AXIS),
450
                   xy_feedrate = fr_mm_s ?: feedRate_t(XY_PROBE_FEEDRATE_MM_S);
467
                   xy_feedrate = fr_mm_s ?: feedRate_t(XY_PROBE_FEEDRATE_MM_S);
529
 }
546
 }
530
 
547
 
531
 void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
548
 void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
532
-  do_blocking_move_to(raw.x, raw.y, current_position.z, fr_mm_s);
549
+  do_blocking_move_to(LINEAR_AXIS_LIST(raw.x, raw.y, current_position.z, current_position.i), fr_mm_s);
533
 }
550
 }
534
 void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
551
 void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
535
-  do_blocking_move_to(raw.x, raw.y, raw.z, fr_mm_s);
552
+  do_blocking_move_to(LINEAR_AXIS_LIST(raw.x, raw.y, raw.z), fr_mm_s);
536
 }
553
 }
537
 void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
554
 void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
538
-  do_blocking_move_to(raw.x, raw.y, raw.z, fr_mm_s);
555
+  do_blocking_move_to(LINEAR_AXIS_LIST(raw.x, raw.y, raw.z), fr_mm_s);
539
 }
556
 }
540
 
557
 
541
 void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) {
558
 void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) {
542
-  do_blocking_move_to(rx, current_position.y, current_position.z, fr_mm_s);
559
+  do_blocking_move_to(
560
+    LINEAR_AXIS_LIST(rx, current_position.y, current_position.z),
561
+    fr_mm_s
562
+  );
543
 }
563
 }
544
 void do_blocking_move_to_y(const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) {
564
 void do_blocking_move_to_y(const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) {
545
-  do_blocking_move_to(current_position.x, ry, current_position.z, fr_mm_s);
565
+  do_blocking_move_to(
566
+    LINEAR_AXIS_LIST(current_position.x, ry, current_position.z),
567
+    fr_mm_s
568
+  );
546
 }
569
 }
547
 void do_blocking_move_to_z(const_float_t rz, const_feedRate_t fr_mm_s/*=0.0*/) {
570
 void do_blocking_move_to_z(const_float_t rz, const_feedRate_t fr_mm_s/*=0.0*/) {
548
   do_blocking_move_to_xy_z(current_position, rz, fr_mm_s);
571
   do_blocking_move_to_xy_z(current_position, rz, fr_mm_s);
549
 }
572
 }
550
 
573
 
551
 void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) {
574
 void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) {
552
-  do_blocking_move_to(rx, ry, current_position.z, fr_mm_s);
575
+  do_blocking_move_to(
576
+    LINEAR_AXIS_LIST(rx, ry, current_position.z),
577
+    fr_mm_s
578
+  );
553
 }
579
 }
554
 void do_blocking_move_to_xy(const xy_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
580
 void do_blocking_move_to_xy(const xy_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) {
555
   do_blocking_move_to_xy(raw.x, raw.y, fr_mm_s);
581
   do_blocking_move_to_xy(raw.x, raw.y, fr_mm_s);
556
 }
582
 }
557
 
583
 
558
 void do_blocking_move_to_xy_z(const xy_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s/*=0.0f*/) {
584
 void do_blocking_move_to_xy_z(const xy_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s/*=0.0f*/) {
559
-  do_blocking_move_to(raw.x, raw.y, z, fr_mm_s);
585
+  do_blocking_move_to(
586
+    LINEAR_AXIS_LIST(raw.x, raw.y, z),
587
+    fr_mm_s
588
+  );
560
 }
589
 }
561
 
590
 
562
 void do_z_clearance(const_float_t zclear, const bool lower_allowed/*=false*/) {
591
 void do_z_clearance(const_float_t zclear, const bool lower_allowed/*=false*/) {
589
   // Software Endstops are based on the configured limits.
618
   // Software Endstops are based on the configured limits.
590
   soft_endstops_t soft_endstop = {
619
   soft_endstops_t soft_endstop = {
591
     true, false,
620
     true, false,
592
-    { X_MIN_POS, Y_MIN_POS, Z_MIN_POS },
593
-    { X_MAX_POS, Y_MAX_POS, Z_MAX_POS }
621
+    LINEAR_AXIS_ARRAY(X_MIN_POS, Y_MIN_POS, Z_MIN_POS),
622
+    LINEAR_AXIS_ARRAY(X_MAX_BED, Y_MAX_BED, Z_MAX_POS)
594
   };
623
   };
595
 
624
 
596
   /**
625
   /**
1176
       if (TEST(b, a) && TERN(HOME_AFTER_DEACTIVATE, axis_is_trusted, axis_was_homed)(a))
1205
       if (TEST(b, a) && TERN(HOME_AFTER_DEACTIVATE, axis_is_trusted, axis_was_homed)(a))
1177
         CBI(b, a);
1206
         CBI(b, a);
1178
     };
1207
     };
1179
-    set_should(axis_bits, X_AXIS);  // Clear test bits that are trusted
1180
-    set_should(axis_bits, Y_AXIS);
1181
-    set_should(axis_bits, Z_AXIS);
1208
+    // Clear test bits that are trusted
1209
+    LINEAR_AXIS_CODE(
1210
+      set_should(axis_bits, X_AXIS),
1211
+      set_should(axis_bits, Y_AXIS),
1212
+      set_should(axis_bits, Z_AXIS)
1213
+    );
1182
     return axis_bits;
1214
     return axis_bits;
1183
   }
1215
   }
1184
 
1216
 
1187
       PGM_P home_first = GET_TEXT(MSG_HOME_FIRST);
1219
       PGM_P home_first = GET_TEXT(MSG_HOME_FIRST);
1188
       char msg[strlen_P(home_first)+1];
1220
       char msg[strlen_P(home_first)+1];
1189
       sprintf_P(msg, home_first,
1221
       sprintf_P(msg, home_first,
1190
-        TEST(axis_bits, X_AXIS) ? "X" : "",
1191
-        TEST(axis_bits, Y_AXIS) ? "Y" : "",
1192
-        TEST(axis_bits, Z_AXIS) ? "Z" : ""
1222
+        LINEAR_AXIS_LIST(
1223
+          TEST(axis_bits, X_AXIS) ? "X" : "",
1224
+          TEST(axis_bits, Y_AXIS) ? "Y" : "",
1225
+          TEST(axis_bits, Z_AXIS) ? "Z" : ""
1226
+        )
1193
       );
1227
       );
1194
       SERIAL_ECHO_START();
1228
       SERIAL_ECHO_START();
1195
       SERIAL_ECHOLN(msg);
1229
       SERIAL_ECHOLN(msg);
1356
     const feedRate_t home_fr_mm_s = fr_mm_s ?: homing_feedrate(axis);
1390
     const feedRate_t home_fr_mm_s = fr_mm_s ?: homing_feedrate(axis);
1357
 
1391
 
1358
     if (DEBUGGING(LEVELING)) {
1392
     if (DEBUGGING(LEVELING)) {
1359
-      DEBUG_ECHOPAIR("...(", AS_CHAR(axis_codes[axis]), ", ", distance, ", ");
1393
+      DEBUG_ECHOPAIR("...(", AS_CHAR(AXIS_CHAR(axis)), ", ", distance, ", ");
1360
       if (fr_mm_s)
1394
       if (fr_mm_s)
1361
         DEBUG_ECHO(fr_mm_s);
1395
         DEBUG_ECHO(fr_mm_s);
1362
       else
1396
       else
1441
    * "trusted" position).
1475
    * "trusted" position).
1442
    */
1476
    */
1443
   void set_axis_never_homed(const AxisEnum axis) {
1477
   void set_axis_never_homed(const AxisEnum axis) {
1444
-    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR(">>> set_axis_never_homed(", AS_CHAR(axis_codes[axis]), ")");
1478
+    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR(">>> set_axis_never_homed(", AS_CHAR(AXIS_CHAR(axis)), ")");
1445
 
1479
 
1446
     set_axis_untrusted(axis);
1480
     set_axis_untrusted(axis);
1447
     set_axis_unhomed(axis);
1481
     set_axis_unhomed(axis);
1448
 
1482
 
1449
-    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("<<< set_axis_never_homed(", AS_CHAR(axis_codes[axis]), ")");
1483
+    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("<<< set_axis_never_homed(", AS_CHAR(AXIS_CHAR(axis)), ")");
1450
 
1484
 
1451
     TERN_(I2C_POSITION_ENCODERS, I2CPEM.unhomed(axis));
1485
     TERN_(I2C_POSITION_ENCODERS, I2CPEM.unhomed(axis));
1452
   }
1486
   }
1507
       if (ABS(phaseDelta) * planner.steps_to_mm[axis] / phasePerUStep < 0.05f)
1541
       if (ABS(phaseDelta) * planner.steps_to_mm[axis] / phasePerUStep < 0.05f)
1508
         SERIAL_ECHOLNPAIR("Selected home phase ", home_phase[axis],
1542
         SERIAL_ECHOLNPAIR("Selected home phase ", home_phase[axis],
1509
                          " too close to endstop trigger phase ", phaseCurrent,
1543
                          " too close to endstop trigger phase ", phaseCurrent,
1510
-                         ". Pick a different phase for ", AS_CHAR(axis_codes[axis]));
1544
+                         ". Pick a different phase for ", AS_CHAR(AXIS_CHAR(axis)));
1511
 
1545
 
1512
       // Skip to next if target position is behind current. So it only moves away from endstop.
1546
       // Skip to next if target position is behind current. So it only moves away from endstop.
1513
       if (phaseDelta < 0) phaseDelta += 1024;
1547
       if (phaseDelta < 0) phaseDelta += 1024;
1518
       // Optional debug messages
1552
       // Optional debug messages
1519
       if (DEBUGGING(LEVELING)) {
1553
       if (DEBUGGING(LEVELING)) {
1520
         DEBUG_ECHOLNPAIR(
1554
         DEBUG_ECHOLNPAIR(
1521
-          "Endstop ", AS_CHAR(axis_codes[axis]), " hit at Phase:", phaseCurrent,
1555
+          "Endstop ", AS_CHAR(AXIS_CHAR(axis)), " hit at Phase:", phaseCurrent,
1522
           " Delta:", phaseDelta, " Distance:", mmDelta
1556
           " Delta:", phaseDelta, " Distance:", mmDelta
1523
         );
1557
         );
1524
       }
1558
       }
1556
       if (!_CAN_HOME(X) && !_CAN_HOME(Y) && !_CAN_HOME(Z)) return;
1590
       if (!_CAN_HOME(X) && !_CAN_HOME(Y) && !_CAN_HOME(Z)) return;
1557
     #endif
1591
     #endif
1558
 
1592
 
1559
-    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR(">>> homeaxis(", AS_CHAR(axis_codes[axis]), ")");
1593
+    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR(">>> homeaxis(", AS_CHAR(AXIS_CHAR(axis)), ")");
1560
 
1594
 
1561
     const int axis_home_dir = TERN0(DUAL_X_CARRIAGE, axis == X_AXIS)
1595
     const int axis_home_dir = TERN0(DUAL_X_CARRIAGE, axis == X_AXIS)
1562
                 ? TOOL_X_HOME_DIR(active_extruder) : home_dir(axis);
1596
                 ? TOOL_X_HOME_DIR(active_extruder) : home_dir(axis);
1634
           case Z_AXIS: es = Z_ENDSTOP; break;
1668
           case Z_AXIS: es = Z_ENDSTOP; break;
1635
         }
1669
         }
1636
         if (TEST(endstops.state(), es)) {
1670
         if (TEST(endstops.state(), es)) {
1637
-          SERIAL_ECHO_MSG("Bad ", AS_CHAR(axis_codes[axis]), " Endstop?");
1671
+          SERIAL_ECHO_MSG("Bad ", AS_CHAR(AXIS_CHAR(axis)), " Endstop?");
1638
           kill(GET_TEXT(MSG_KILL_HOMING_FAILED));
1672
           kill(GET_TEXT(MSG_KILL_HOMING_FAILED));
1639
         }
1673
         }
1640
       #endif
1674
       #endif
1856
       if (axis == Z_AXIS) fwretract.current_hop = 0.0;
1890
       if (axis == Z_AXIS) fwretract.current_hop = 0.0;
1857
     #endif
1891
     #endif
1858
 
1892
 
1859
-    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("<<< homeaxis(", AS_CHAR(axis_codes[axis]), ")");
1893
+    if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("<<< homeaxis(", AS_CHAR(AXIS_CHAR(axis)), ")");
1860
 
1894
 
1861
   } // homeaxis()
1895
   } // homeaxis()
1862
 
1896
 
1881
  * Callers must sync the planner position after calling this!
1915
  * Callers must sync the planner position after calling this!
1882
  */
1916
  */
1883
 void set_axis_is_at_home(const AxisEnum axis) {
1917
 void set_axis_is_at_home(const AxisEnum axis) {
1884
-  if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR(">>> set_axis_is_at_home(", AS_CHAR(axis_codes[axis]), ")");
1918
+  if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR(">>> set_axis_is_at_home(", AS_CHAR(AXIS_CHAR(axis)), ")");
1885
 
1919
 
1886
   set_axis_trusted(axis);
1920
   set_axis_trusted(axis);
1887
   set_axis_homed(axis);
1921
   set_axis_homed(axis);
1931
 
1965
 
1932
   if (DEBUGGING(LEVELING)) {
1966
   if (DEBUGGING(LEVELING)) {
1933
     #if HAS_HOME_OFFSET
1967
     #if HAS_HOME_OFFSET
1934
-      DEBUG_ECHOLNPAIR("> home_offset[", AS_CHAR(axis_codes[axis]), "] = ", home_offset[axis]);
1968
+      DEBUG_ECHOLNPAIR("> home_offset[", AS_CHAR(AXIS_CHAR(axis)), "] = ", home_offset[axis]);
1935
     #endif
1969
     #endif
1936
     DEBUG_POS("", current_position);
1970
     DEBUG_POS("", current_position);
1937
-    DEBUG_ECHOLNPAIR("<<< set_axis_is_at_home(", AS_CHAR(axis_codes[axis]), ")");
1971
+    DEBUG_ECHOLNPAIR("<<< set_axis_is_at_home(", AS_CHAR(AXIS_CHAR(axis)), ")");
1938
   }
1972
   }
1939
 }
1973
 }
1940
 
1974
 

+ 10
- 4
Marlin/src/module/motion.h 查看文件

124
 
124
 
125
 #define XYZ_DEFS(T, NAME, OPT) \
125
 #define XYZ_DEFS(T, NAME, OPT) \
126
   inline T NAME(const AxisEnum axis) { \
126
   inline T NAME(const AxisEnum axis) { \
127
-    static const XYZval<T> NAME##_P DEFS_PROGMEM = { X_##OPT, Y_##OPT, Z_##OPT }; \
127
+    static const XYZval<T> NAME##_P DEFS_PROGMEM = LINEAR_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT); \
128
     return pgm_read_any(&NAME##_P[axis]); \
128
     return pgm_read_any(&NAME##_P[axis]); \
129
   }
129
   }
130
 XYZ_DEFS(float, base_min_pos,   MIN_POS);
130
 XYZ_DEFS(float, base_min_pos,   MIN_POS);
264
  * no kinematic translation. Used for homing axes and cartesian/core syncing.
264
  * no kinematic translation. Used for homing axes and cartesian/core syncing.
265
  */
265
  */
266
 void sync_plan_position();
266
 void sync_plan_position();
267
-void sync_plan_position_e();
267
+
268
+#if HAS_EXTRUDERS
269
+  void sync_plan_position_e();
270
+#endif
268
 
271
 
269
 /**
272
 /**
270
  * Move the planner to the current position from wherever it last moved
273
  * Move the planner to the current position from wherever it last moved
295
 /**
298
 /**
296
  * Blocking movement and shorthand functions
299
  * Blocking movement and shorthand functions
297
  */
300
  */
298
-void do_blocking_move_to(const float rx, const float ry, const float rz, const_feedRate_t fr_mm_s=0.0f);
301
+void do_blocking_move_to(
302
+  LINEAR_AXIS_LIST(const float rx, const float ry, const float rz),
303
+  const_feedRate_t fr_mm_s=0.0f
304
+);
299
 void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
305
 void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
300
 void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
306
 void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
301
 void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
307
 void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f);
322
 /**
328
 /**
323
  * Homing and Trusted Axes
329
  * Homing and Trusted Axes
324
  */
330
  */
325
-typedef IF<(LINEAR_AXES>8), uint16_t, uint8_t>::type linear_axis_bits_t;
331
+typedef IF<(LINEAR_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t;
326
 constexpr linear_axis_bits_t linear_bits = _BV(LINEAR_AXES) - 1;
332
 constexpr linear_axis_bits_t linear_bits = _BV(LINEAR_AXES) - 1;
327
 
333
 
328
 void set_axis_is_at_home(const AxisEnum axis);
334
 void set_axis_is_at_home(const AxisEnum axis);

+ 153
- 113
Marlin/src/module/planner.cpp 查看文件

1345
     #if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_E)
1345
     #if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_E)
1346
       for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
1346
       for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
1347
         block_t *block = &block_buffer[b];
1347
         block_t *block = &block_buffer[b];
1348
-        if (ENABLED(DISABLE_X) && block->steps.x) axis_active.x = true;
1349
-        if (ENABLED(DISABLE_Y) && block->steps.y) axis_active.y = true;
1350
-        if (ENABLED(DISABLE_Z) && block->steps.z) axis_active.z = true;
1351
-        if (ENABLED(DISABLE_E) && block->steps.e) axis_active.e = true;
1348
+        LOGICAL_AXIS_CODE(
1349
+          if (TERN0(DISABLE_E, block->steps.e)) axis_active.e = true,
1350
+          if (TERN0(DISABLE_X, block->steps.x)) axis_active.x = true,
1351
+          if (TERN0(DISABLE_Y, block->steps.y)) axis_active.y = true,
1352
+          if (TERN0(DISABLE_Z, block->steps.z)) axis_active.z = true
1353
+        );
1352
       }
1354
       }
1353
     #endif
1355
     #endif
1354
   }
1356
   }
1369
   //
1371
   //
1370
   // Disable inactive axes
1372
   // Disable inactive axes
1371
   //
1373
   //
1372
-  if (TERN0(DISABLE_X, !axis_active.x)) DISABLE_AXIS_X();
1373
-  if (TERN0(DISABLE_Y, !axis_active.y)) DISABLE_AXIS_Y();
1374
-  if (TERN0(DISABLE_Z, !axis_active.z)) DISABLE_AXIS_Z();
1375
-  if (TERN0(DISABLE_E, !axis_active.e)) disable_e_steppers();
1374
+  LOGICAL_AXIS_CODE(
1375
+    if (TERN0(DISABLE_E, !axis_active.e)) disable_e_steppers(),
1376
+    if (TERN0(DISABLE_X, !axis_active.x)) DISABLE_AXIS_X(),
1377
+    if (TERN0(DISABLE_Y, !axis_active.y)) DISABLE_AXIS_Y(),
1378
+    if (TERN0(DISABLE_Z, !axis_active.z)) DISABLE_AXIS_Z()
1379
+  );
1376
 
1380
 
1377
   //
1381
   //
1378
   // Update Fan speeds
1382
   // Update Fan speeds
1823
   OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
1827
   OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
1824
   , feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters/*=0.0*/
1828
   , feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters/*=0.0*/
1825
 ) {
1829
 ) {
1826
-
1827
-  const int32_t da = target.a - position.a,
1828
-                db = target.b - position.b,
1829
-                dc = target.c - position.c;
1830
-
1831
-  #if HAS_EXTRUDERS
1832
-    int32_t de = target.e - position.e;
1833
-  #else
1834
-    constexpr int32_t de = 0;
1835
-  #endif
1830
+  int32_t LOGICAL_AXIS_LIST(
1831
+    de = target.e - position.e,
1832
+    da = target.a - position.a,
1833
+    db = target.b - position.b,
1834
+    dc = target.c - position.c
1835
+  );
1836
 
1836
 
1837
   /* <-- add a slash to enable
1837
   /* <-- add a slash to enable
1838
     SERIAL_ECHOLNPAIR(
1838
     SERIAL_ECHOLNPAIR(
1883
   // Compute direction bit-mask for this block
1883
   // Compute direction bit-mask for this block
1884
   uint8_t dm = 0;
1884
   uint8_t dm = 0;
1885
   #if CORE_IS_XY
1885
   #if CORE_IS_XY
1886
-    if (da < 0) SBI(dm, X_HEAD);                // Save the real Extruder (head) direction in X Axis
1886
+    if (da < 0) SBI(dm, X_HEAD);                // Save the toolhead's true direction in X
1887
     if (db < 0) SBI(dm, Y_HEAD);                // ...and Y
1887
     if (db < 0) SBI(dm, Y_HEAD);                // ...and Y
1888
     if (dc < 0) SBI(dm, Z_AXIS);
1888
     if (dc < 0) SBI(dm, Z_AXIS);
1889
     if (da + db < 0) SBI(dm, A_AXIS);           // Motor A direction
1889
     if (da + db < 0) SBI(dm, A_AXIS);           // Motor A direction
1890
     if (CORESIGN(da - db) < 0) SBI(dm, B_AXIS); // Motor B direction
1890
     if (CORESIGN(da - db) < 0) SBI(dm, B_AXIS); // Motor B direction
1891
   #elif CORE_IS_XZ
1891
   #elif CORE_IS_XZ
1892
-    if (da < 0) SBI(dm, X_HEAD);                // Save the real Extruder (head) direction in X Axis
1892
+    if (da < 0) SBI(dm, X_HEAD);                // Save the toolhead's true direction in X
1893
     if (db < 0) SBI(dm, Y_AXIS);
1893
     if (db < 0) SBI(dm, Y_AXIS);
1894
     if (dc < 0) SBI(dm, Z_HEAD);                // ...and Z
1894
     if (dc < 0) SBI(dm, Z_HEAD);                // ...and Z
1895
     if (da + dc < 0) SBI(dm, A_AXIS);           // Motor A direction
1895
     if (da + dc < 0) SBI(dm, A_AXIS);           // Motor A direction
1896
     if (CORESIGN(da - dc) < 0) SBI(dm, C_AXIS); // Motor C direction
1896
     if (CORESIGN(da - dc) < 0) SBI(dm, C_AXIS); // Motor C direction
1897
   #elif CORE_IS_YZ
1897
   #elif CORE_IS_YZ
1898
     if (da < 0) SBI(dm, X_AXIS);
1898
     if (da < 0) SBI(dm, X_AXIS);
1899
-    if (db < 0) SBI(dm, Y_HEAD);                // Save the real Extruder (head) direction in Y Axis
1899
+    if (db < 0) SBI(dm, Y_HEAD);                // Save the toolhead's true direction in Y
1900
     if (dc < 0) SBI(dm, Z_HEAD);                // ...and Z
1900
     if (dc < 0) SBI(dm, Z_HEAD);                // ...and Z
1901
     if (db + dc < 0) SBI(dm, B_AXIS);           // Motor B direction
1901
     if (db + dc < 0) SBI(dm, B_AXIS);           // Motor B direction
1902
     if (CORESIGN(db - dc) < 0) SBI(dm, C_AXIS); // Motor C direction
1902
     if (CORESIGN(db - dc) < 0) SBI(dm, C_AXIS); // Motor C direction
1903
   #elif ENABLED(MARKFORGED_XY)
1903
   #elif ENABLED(MARKFORGED_XY)
1904
-    if (da < 0) SBI(dm, X_HEAD);                // Save the real Extruder (head) direction in X Axis
1904
+    if (da < 0) SBI(dm, X_HEAD);                // Save the toolhead's true direction in X
1905
     if (db < 0) SBI(dm, Y_HEAD);                // ...and Y
1905
     if (db < 0) SBI(dm, Y_HEAD);                // ...and Y
1906
     if (dc < 0) SBI(dm, Z_AXIS);
1906
     if (dc < 0) SBI(dm, Z_AXIS);
1907
     if (da + db < 0) SBI(dm, A_AXIS);           // Motor A direction
1907
     if (da + db < 0) SBI(dm, A_AXIS);           // Motor A direction
1908
     if (db < 0) SBI(dm, B_AXIS);                // Motor B direction
1908
     if (db < 0) SBI(dm, B_AXIS);                // Motor B direction
1909
   #else
1909
   #else
1910
-    if (da < 0) SBI(dm, X_AXIS);
1911
-    if (db < 0) SBI(dm, Y_AXIS);
1912
-    if (dc < 0) SBI(dm, Z_AXIS);
1910
+    LINEAR_AXIS_CODE(
1911
+      if (da < 0) SBI(dm, X_AXIS),
1912
+      if (db < 0) SBI(dm, Y_AXIS),
1913
+      if (dc < 0) SBI(dm, Z_AXIS)
1914
+    );
1915
+  #endif
1916
+  #if HAS_EXTRUDERS
1917
+    if (de < 0) SBI(dm, E_AXIS);
1913
   #endif
1918
   #endif
1914
-  if (de < 0) SBI(dm, E_AXIS);
1915
 
1919
 
1916
   #if HAS_EXTRUDERS
1920
   #if HAS_EXTRUDERS
1917
     const float esteps_float = de * e_factor[extruder];
1921
     const float esteps_float = de * e_factor[extruder];
1947
     block->steps.set(ABS(da), ABS(db), ABS(dc));
1951
     block->steps.set(ABS(da), ABS(db), ABS(dc));
1948
   #else
1952
   #else
1949
     // default non-h-bot planning
1953
     // default non-h-bot planning
1950
-    block->steps.set(ABS(da), ABS(db), ABS(dc));
1954
+    block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db), ABS(dc)));
1951
   #endif
1955
   #endif
1952
 
1956
 
1953
   /**
1957
   /**
1990
     steps_dist_mm.a      = (da - db) * steps_to_mm[A_AXIS];
1994
     steps_dist_mm.a      = (da - db) * steps_to_mm[A_AXIS];
1991
     steps_dist_mm.b      = db * steps_to_mm[B_AXIS];
1995
     steps_dist_mm.b      = db * steps_to_mm[B_AXIS];
1992
   #else
1996
   #else
1993
-    steps_dist_mm.a = da * steps_to_mm[A_AXIS];
1994
-    steps_dist_mm.b = db * steps_to_mm[B_AXIS];
1995
-    steps_dist_mm.c = dc * steps_to_mm[C_AXIS];
1997
+    LINEAR_AXIS_CODE(
1998
+      steps_dist_mm.a = da * steps_to_mm[A_AXIS],
1999
+      steps_dist_mm.b = db * steps_to_mm[B_AXIS],
2000
+      steps_dist_mm.c = dc * steps_to_mm[C_AXIS]
2001
+    );
1996
   #endif
2002
   #endif
1997
 
2003
 
1998
   #if HAS_EXTRUDERS
2004
   #if HAS_EXTRUDERS
1999
     steps_dist_mm.e = esteps_float * steps_to_mm[E_AXIS_N(extruder)];
2005
     steps_dist_mm.e = esteps_float * steps_to_mm[E_AXIS_N(extruder)];
2000
-  #else
2001
-    steps_dist_mm.e = 0.0f;
2002
   #endif
2006
   #endif
2003
 
2007
 
2004
   TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator += steps_dist_mm.e);
2008
   TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator += steps_dist_mm.e);
2005
 
2009
 
2006
-  if (block->steps.a < MIN_STEPS_PER_SEGMENT && block->steps.b < MIN_STEPS_PER_SEGMENT && block->steps.c < MIN_STEPS_PER_SEGMENT) {
2007
-    block->millimeters = (0
2008
-      #if HAS_EXTRUDERS
2009
-        + ABS(steps_dist_mm.e)
2010
-      #endif
2011
-    );
2010
+  if (true LINEAR_AXIS_GANG(
2011
+      && block->steps.a < MIN_STEPS_PER_SEGMENT,
2012
+      && block->steps.b < MIN_STEPS_PER_SEGMENT,
2013
+      && block->steps.c < MIN_STEPS_PER_SEGMENT
2014
+    )
2015
+  ) {
2016
+    block->millimeters = TERN0(HAS_EXTRUDERS, ABS(steps_dist_mm.e));
2012
   }
2017
   }
2013
   else {
2018
   else {
2014
     if (millimeters)
2019
     if (millimeters)
2015
       block->millimeters = millimeters;
2020
       block->millimeters = millimeters;
2016
-    else
2021
+    else {
2017
       block->millimeters = SQRT(
2022
       block->millimeters = SQRT(
2018
         #if EITHER(CORE_IS_XY, MARKFORGED_XY)
2023
         #if EITHER(CORE_IS_XY, MARKFORGED_XY)
2019
-          sq(steps_dist_mm.head.x) + sq(steps_dist_mm.head.y) + sq(steps_dist_mm.z)
2024
+          LINEAR_AXIS_GANG(
2025
+            sq(steps_dist_mm.head.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.z)
2026
+          )
2020
         #elif CORE_IS_XZ
2027
         #elif CORE_IS_XZ
2021
-          sq(steps_dist_mm.head.x) + sq(steps_dist_mm.y) + sq(steps_dist_mm.head.z)
2028
+          LINEAR_AXIS_GANG(
2029
+            sq(steps_dist_mm.head.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.head.z)
2030
+          )
2022
         #elif CORE_IS_YZ
2031
         #elif CORE_IS_YZ
2023
-          sq(steps_dist_mm.x) + sq(steps_dist_mm.head.y) + sq(steps_dist_mm.head.z)
2032
+          LINEAR_AXIS_GANG(
2033
+            sq(steps_dist_mm.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.head.z)
2034
+          )
2024
         #else
2035
         #else
2025
-          sq(steps_dist_mm.x) + sq(steps_dist_mm.y) + sq(steps_dist_mm.z)
2036
+          LINEAR_AXIS_GANG(
2037
+            sq(steps_dist_mm.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.z)
2038
+          )
2026
         #endif
2039
         #endif
2027
       );
2040
       );
2041
+    }
2028
 
2042
 
2029
     /**
2043
     /**
2030
      * At this point at least one of the axes has more steps than
2044
      * At this point at least one of the axes has more steps than
2038
     TERN_(BACKLASH_COMPENSATION, backlash.add_correction_steps(da, db, dc, dm, block));
2052
     TERN_(BACKLASH_COMPENSATION, backlash.add_correction_steps(da, db, dc, dm, block));
2039
   }
2053
   }
2040
 
2054
 
2041
-  #if HAS_EXTRUDERS
2042
-    block->steps.e = esteps;
2043
-  #endif
2055
+  TERN_(HAS_EXTRUDERS, block->steps.e = esteps);
2044
 
2056
 
2045
-  block->step_event_count = _MAX(block->steps.a, block->steps.b, block->steps.c, esteps);
2057
+  block->step_event_count = _MAX(LOGICAL_AXIS_LIST(
2058
+    esteps, block->steps.a, block->steps.b, block->steps.c
2059
+  ));
2046
 
2060
 
2047
   // Bail if this is a zero-length block
2061
   // Bail if this is a zero-length block
2048
   if (block->step_event_count < MIN_STEPS_PER_SEGMENT) return false;
2062
   if (block->step_event_count < MIN_STEPS_PER_SEGMENT) return false;
2065
   #endif
2079
   #endif
2066
 
2080
 
2067
   #if ENABLED(AUTO_POWER_CONTROL)
2081
   #if ENABLED(AUTO_POWER_CONTROL)
2068
-    if (block->steps.x || block->steps.y || block->steps.z)
2069
-      powerManager.power_on();
2082
+    if (LINEAR_AXIS_GANG(
2083
+         block->steps.x,
2084
+      || block->steps.y,
2085
+      || block->steps.z
2086
+    )) powerManager.power_on();
2070
   #endif
2087
   #endif
2071
 
2088
 
2072
   // Enable active axes
2089
   // Enable active axes
2091
     }
2108
     }
2092
     if (block->steps.x) ENABLE_AXIS_X();
2109
     if (block->steps.x) ENABLE_AXIS_X();
2093
   #else
2110
   #else
2094
-    if (block->steps.x) ENABLE_AXIS_X();
2095
-    if (block->steps.y) ENABLE_AXIS_Y();
2096
-    #if DISABLED(Z_LATE_ENABLE)
2097
-      if (block->steps.z) ENABLE_AXIS_Z();
2098
-    #endif
2111
+    LINEAR_AXIS_CODE(
2112
+      if (block->steps.x) ENABLE_AXIS_X(),
2113
+      if (block->steps.y) ENABLE_AXIS_Y(),
2114
+      if (TERN(Z_LATE_ENABLE, 0, block->steps.z)) ENABLE_AXIS_Z()
2115
+    );
2099
   #endif
2116
   #endif
2100
 
2117
 
2101
   // Enable extruder(s)
2118
   // Enable extruder(s)
2281
   // Compute and limit the acceleration rate for the trapezoid generator.
2298
   // Compute and limit the acceleration rate for the trapezoid generator.
2282
   const float steps_per_mm = block->step_event_count * inverse_millimeters;
2299
   const float steps_per_mm = block->step_event_count * inverse_millimeters;
2283
   uint32_t accel;
2300
   uint32_t accel;
2284
-  if (!block->steps.a && !block->steps.b && !block->steps.c) {    // Is this a retract / recover move?
2301
+  if (LINEAR_AXIS_GANG(
2302
+    !block->steps.a, && !block->steps.b, && !block->steps.c
2303
+  )) {                                                            // Is this a retract / recover move?
2285
     accel = CEIL(settings.retract_acceleration * steps_per_mm);   // Convert to: acceleration steps/sec^2
2304
     accel = CEIL(settings.retract_acceleration * steps_per_mm);   // Convert to: acceleration steps/sec^2
2286
     TERN_(LIN_ADVANCE, block->use_advance_lead = false);          // No linear advance for simple retract/recover
2305
     TERN_(LIN_ADVANCE, block->use_advance_lead = false);          // No linear advance for simple retract/recover
2287
   }
2306
   }
2346
 
2365
 
2347
     // Limit acceleration per axis
2366
     // Limit acceleration per axis
2348
     if (block->step_event_count <= acceleration_long_cutoff) {
2367
     if (block->step_event_count <= acceleration_long_cutoff) {
2349
-      LIMIT_ACCEL_LONG(A_AXIS, 0);
2350
-      LIMIT_ACCEL_LONG(B_AXIS, 0);
2351
-      LIMIT_ACCEL_LONG(C_AXIS, 0);
2352
-      LIMIT_ACCEL_LONG(E_AXIS, E_INDEX_N(extruder));
2368
+      LOGICAL_AXIS_CODE(
2369
+        LIMIT_ACCEL_LONG(E_AXIS, E_INDEX_N(extruder)),
2370
+        LIMIT_ACCEL_LONG(A_AXIS, 0),
2371
+        LIMIT_ACCEL_LONG(B_AXIS, 0),
2372
+        LIMIT_ACCEL_LONG(C_AXIS, 0)
2373
+      );
2353
     }
2374
     }
2354
     else {
2375
     else {
2355
-      LIMIT_ACCEL_FLOAT(A_AXIS, 0);
2356
-      LIMIT_ACCEL_FLOAT(B_AXIS, 0);
2357
-      LIMIT_ACCEL_FLOAT(C_AXIS, 0);
2358
-      LIMIT_ACCEL_FLOAT(E_AXIS, E_INDEX_N(extruder));
2376
+      LOGICAL_AXIS_CODE(
2377
+        LIMIT_ACCEL_FLOAT(E_AXIS, E_INDEX_N(extruder)),
2378
+        LIMIT_ACCEL_FLOAT(A_AXIS, 0),
2379
+        LIMIT_ACCEL_FLOAT(B_AXIS, 0),
2380
+        LIMIT_ACCEL_FLOAT(C_AXIS, 0)
2381
+      );
2359
     }
2382
     }
2360
   }
2383
   }
2361
   block->acceleration_steps_per_s2 = accel;
2384
   block->acceleration_steps_per_s2 = accel;
2419
       #if HAS_DIST_MM_ARG
2442
       #if HAS_DIST_MM_ARG
2420
         cart_dist_mm
2443
         cart_dist_mm
2421
       #else
2444
       #else
2422
-        { steps_dist_mm.x, steps_dist_mm.y, steps_dist_mm.z, steps_dist_mm.e }
2445
+        LOGICAL_AXIS_ARRAY(steps_dist_mm.e, steps_dist_mm.x, steps_dist_mm.y, steps_dist_mm.z)
2423
       #endif
2446
       #endif
2424
     ;
2447
     ;
2425
 
2448
 
2438
     if (moves_queued && !UNEAR_ZERO(previous_nominal_speed_sqr)) {
2461
     if (moves_queued && !UNEAR_ZERO(previous_nominal_speed_sqr)) {
2439
       // Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
2462
       // Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
2440
       // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
2463
       // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
2441
-      float junction_cos_theta = (-prev_unit_vec.x * unit_vec.x) + (-prev_unit_vec.y * unit_vec.y)
2442
-                               + (-prev_unit_vec.z * unit_vec.z) + (-prev_unit_vec.e * unit_vec.e);
2464
+      float junction_cos_theta = LOGICAL_AXIS_GANG(
2465
+                                 + (-prev_unit_vec.e * unit_vec.e),
2466
+                                   (-prev_unit_vec.x * unit_vec.x),
2467
+                                 + (-prev_unit_vec.y * unit_vec.y),
2468
+                                 + (-prev_unit_vec.z * unit_vec.z)
2469
+                               );
2443
 
2470
 
2444
       // NOTE: Computed without any expensive trig, sin() or acos(), by trig half angle identity of cos(theta).
2471
       // NOTE: Computed without any expensive trig, sin() or acos(), by trig half angle identity of cos(theta).
2445
       if (junction_cos_theta > 0.999999f) {
2472
       if (junction_cos_theta > 0.999999f) {
2754
  *
2781
  *
2755
  * Return 'false' if no segment was queued due to cleaning, cold extrusion, full queue, etc.
2782
  * Return 'false' if no segment was queued due to cleaning, cold extrusion, full queue, etc.
2756
  */
2783
  */
2757
-bool Planner::buffer_segment(const_float_t a, const_float_t b, const_float_t c, const_float_t e
2784
+bool Planner::buffer_segment(
2785
+  LOGICAL_AXIS_LIST(const_float_t e, const_float_t a, const_float_t b, const_float_t c)
2758
   OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
2786
   OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
2759
   , const_feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters/*=0.0*/
2787
   , const_feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters/*=0.0*/
2760
 ) {
2788
 ) {
2773
   // The target position of the tool in absolute steps
2801
   // The target position of the tool in absolute steps
2774
   // Calculate target position in absolute steps
2802
   // Calculate target position in absolute steps
2775
   const abce_long_t target = {
2803
   const abce_long_t target = {
2776
-    int32_t(LROUND(a * settings.axis_steps_per_mm[A_AXIS])),
2777
-    int32_t(LROUND(b * settings.axis_steps_per_mm[B_AXIS])),
2778
-    int32_t(LROUND(c * settings.axis_steps_per_mm[C_AXIS])),
2779
-    int32_t(LROUND(e * settings.axis_steps_per_mm[E_AXIS_N(extruder)]))
2804
+     LOGICAL_AXIS_LIST(
2805
+      int32_t(LROUND(e * settings.axis_steps_per_mm[E_AXIS_N(extruder)])),
2806
+      int32_t(LROUND(a * settings.axis_steps_per_mm[A_AXIS])),
2807
+      int32_t(LROUND(b * settings.axis_steps_per_mm[B_AXIS])),
2808
+      int32_t(LROUND(c * settings.axis_steps_per_mm[C_AXIS]))
2809
+    )
2780
   };
2810
   };
2781
 
2811
 
2782
   #if HAS_POSITION_FLOAT
2812
   #if HAS_POSITION_FLOAT
2783
-    const xyze_pos_t target_float = { a, b, c, e };
2813
+    const xyze_pos_t target_float = LOGICAL_AXIS_ARRAY(e, a, b, c);
2784
   #endif
2814
   #endif
2785
 
2815
 
2786
-  // DRYRUN prevents E moves from taking place
2787
-  if (DEBUGGING(DRYRUN) || TERN0(CANCEL_OBJECTS, cancelable.skipping)) {
2788
-    position.e = target.e;
2789
-    TERN_(HAS_POSITION_FLOAT, position_float.e = e);
2790
-  }
2816
+  #if HAS_EXTRUDERS
2817
+    // DRYRUN prevents E moves from taking place
2818
+    if (DEBUGGING(DRYRUN) || TERN0(CANCEL_OBJECTS, cancelable.skipping)) {
2819
+      position.e = target.e;
2820
+      TERN_(HAS_POSITION_FLOAT, position_float.e = e);
2821
+    }
2822
+  #endif
2791
 
2823
 
2792
   /* <-- add a slash to enable
2824
   /* <-- add a slash to enable
2793
     SERIAL_ECHOPAIR("  buffer_segment FR:", fr_mm_s);
2825
     SERIAL_ECHOPAIR("  buffer_segment FR:", fr_mm_s);
2846
  *  millimeters  - the length of the movement, if known
2878
  *  millimeters  - the length of the movement, if known
2847
  *  inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
2879
  *  inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
2848
  */
2880
  */
2849
-bool Planner::buffer_line(const_float_t rx, const_float_t ry, const_float_t rz, const_float_t e, const_feedRate_t fr_mm_s, const uint8_t extruder, const float millimeters
2881
+bool Planner::buffer_line(
2882
+  LOGICAL_AXIS_LIST(const_float_t e, const_float_t rx, const_float_t ry, const_float_t rz)
2883
+  , const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters
2850
   OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration)
2884
   OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration)
2851
 ) {
2885
 ) {
2852
-  xyze_pos_t machine = { rx, ry, rz, e };
2886
+  xyze_pos_t machine = LOGICAL_AXIS_ARRAY(e, rx, ry, rz);
2853
   TERN_(HAS_POSITION_MODIFIERS, apply_modifiers(machine));
2887
   TERN_(HAS_POSITION_MODIFIERS, apply_modifiers(machine));
2854
 
2888
 
2855
   #if IS_KINEMATIC
2889
   #if IS_KINEMATIC
2912
       FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i];
2946
       FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i];
2913
     #endif
2947
     #endif
2914
 
2948
 
2915
-    #if HAS_MULTI_EXTRUDER
2916
-      block->extruder = extruder;
2917
-    #endif
2949
+    TERN_(HAS_MULTI_EXTRUDER, block->extruder = extruder);
2918
 
2950
 
2919
     block->page_idx = page_idx;
2951
     block->page_idx = page_idx;
2920
 
2952
 
2921
     block->step_event_count = num_steps;
2953
     block->step_event_count = num_steps;
2922
-    block->initial_rate =
2923
-      block->final_rate =
2924
-      block->nominal_rate = last_page_step_rate; // steps/s
2954
+    block->initial_rate = block->final_rate = block->nominal_rate = last_page_step_rate; // steps/s
2925
 
2955
 
2926
     block->accelerate_until = 0;
2956
     block->accelerate_until = 0;
2927
     block->decelerate_after = block->step_event_count;
2957
     block->decelerate_after = block->step_event_count;
2965
  * The provided ABC position is in machine units.
2995
  * The provided ABC position is in machine units.
2966
  */
2996
  */
2967
 
2997
 
2968
-void Planner::set_machine_position_mm(const_float_t a, const_float_t b, const_float_t c, const_float_t e) {
2998
+void Planner::set_machine_position_mm(
2999
+  LOGICAL_AXIS_LIST(const_float_t e, const_float_t a, const_float_t b, const_float_t c)
3000
+) {
2969
   TERN_(DISTINCT_E_FACTORS, last_extruder = active_extruder);
3001
   TERN_(DISTINCT_E_FACTORS, last_extruder = active_extruder);
2970
-  TERN_(HAS_POSITION_FLOAT, position_float.set(a, b, c, e));
2971
-  position.set(LROUND(a * settings.axis_steps_per_mm[A_AXIS]),
2972
-               LROUND(b * settings.axis_steps_per_mm[B_AXIS]),
2973
-               LROUND(c * settings.axis_steps_per_mm[C_AXIS]),
2974
-               LROUND(e * settings.axis_steps_per_mm[E_AXIS_N(active_extruder)]));
3002
+  TERN_(HAS_POSITION_FLOAT, position_float.set(LOGICAL_AXIS_LIST(e, a, b, c)));
3003
+  position.set(
3004
+    LOGICAL_AXIS_LIST(
3005
+      LROUND(e * settings.axis_steps_per_mm[E_AXIS_N(active_extruder)]),
3006
+      LROUND(a * settings.axis_steps_per_mm[A_AXIS]),
3007
+      LROUND(b * settings.axis_steps_per_mm[B_AXIS]),
3008
+      LROUND(c * settings.axis_steps_per_mm[C_AXIS])
3009
+    )
3010
+  );
2975
   if (has_blocks_queued()) {
3011
   if (has_blocks_queued()) {
2976
     //previous_nominal_speed_sqr = 0.0; // Reset planner junction speeds. Assume start from rest.
3012
     //previous_nominal_speed_sqr = 0.0; // Reset planner junction speeds. Assume start from rest.
2977
     //previous_speed.reset();
3013
     //previous_speed.reset();
2981
     stepper.set_position(position);
3017
     stepper.set_position(position);
2982
 }
3018
 }
2983
 
3019
 
2984
-void Planner::set_position_mm(const_float_t rx, const_float_t ry, const_float_t rz, const_float_t e) {
2985
-  xyze_pos_t machine = { rx, ry, rz, e };
2986
-  #if HAS_POSITION_MODIFIERS
2987
-    apply_modifiers(machine, true);
2988
-  #endif
3020
+void Planner::set_position_mm(
3021
+  LOGICAL_AXIS_LIST(const_float_t e, const_float_t rx, const_float_t ry, const_float_t rz)
3022
+) {
3023
+  xyze_pos_t machine = LOGICAL_AXIS_ARRAY(e, rx, ry, rz);
3024
+  TERN_(HAS_POSITION_MODIFIERS, apply_modifiers(machine, true));
2989
   #if IS_KINEMATIC
3025
   #if IS_KINEMATIC
2990
     position_cart.set(rx, ry, rz, e);
3026
     position_cart.set(rx, ry, rz, e);
2991
     inverse_kinematics(machine);
3027
     inverse_kinematics(machine);
2995
   #endif
3031
   #endif
2996
 }
3032
 }
2997
 
3033
 
2998
-/**
2999
- * Setters for planner position (also setting stepper position).
3000
- */
3001
-void Planner::set_e_position_mm(const_float_t e) {
3002
-  const uint8_t axis_index = E_AXIS_N(active_extruder);
3003
-  TERN_(DISTINCT_E_FACTORS, last_extruder = active_extruder);
3034
+#if HAS_EXTRUDERS
3004
 
3035
 
3005
-  const float e_new = DIFF_TERN(FWRETRACT, e, fwretract.current_retract[active_extruder]);
3006
-  position.e = LROUND(settings.axis_steps_per_mm[axis_index] * e_new);
3007
-  TERN_(HAS_POSITION_FLOAT, position_float.e = e_new);
3008
-  TERN_(IS_KINEMATIC, position_cart.e = e);
3036
+  /**
3037
+   * Setters for planner position (also setting stepper position).
3038
+   */
3039
+  void Planner::set_e_position_mm(const_float_t e) {
3040
+    const uint8_t axis_index = E_AXIS_N(active_extruder);
3041
+    TERN_(DISTINCT_E_FACTORS, last_extruder = active_extruder);
3009
 
3042
 
3010
-  if (has_blocks_queued())
3011
-    buffer_sync_block();
3012
-  else
3013
-    stepper.set_axis_position(E_AXIS, position.e);
3014
-}
3043
+    const float e_new = DIFF_TERN(FWRETRACT, e, fwretract.current_retract[active_extruder]);
3044
+    position.e = LROUND(settings.axis_steps_per_mm[axis_index] * e_new);
3045
+    TERN_(HAS_POSITION_FLOAT, position_float.e = e_new);
3046
+    TERN_(IS_KINEMATIC, position_cart.e = e);
3047
+
3048
+    if (has_blocks_queued())
3049
+      buffer_sync_block();
3050
+    else
3051
+      stepper.set_axis_position(E_AXIS, position.e);
3052
+  }
3053
+
3054
+#endif
3015
 
3055
 
3016
 // Recalculate the steps/s^2 acceleration rates, based on the mm/s^2
3056
 // Recalculate the steps/s^2 acceleration rates, based on the mm/s^2
3017
 void Planner::reset_acceleration_rates() {
3057
 void Planner::reset_acceleration_rates() {
3041
 
3081
 
3042
 // Apply limits to a variable and give a warning if the value was out of range
3082
 // Apply limits to a variable and give a warning if the value was out of range
3043
 inline void limit_and_warn(float &val, const uint8_t axis, PGM_P const setting_name, const xyze_float_t &max_limit) {
3083
 inline void limit_and_warn(float &val, const uint8_t axis, PGM_P const setting_name, const xyze_float_t &max_limit) {
3044
-  const uint8_t lim_axis = axis > E_AXIS ? E_AXIS : axis;
3084
+  const uint8_t lim_axis = TERN_(HAS_EXTRUDERS, axis > E_AXIS ? E_AXIS :) axis;
3045
   const float before = val;
3085
   const float before = val;
3046
   LIMIT(val, 0.1, max_limit[lim_axis]);
3086
   LIMIT(val, 0.1, max_limit[lim_axis]);
3047
   if (before != val) {
3087
   if (before != val) {
3048
-    SERIAL_CHAR(axis_codes[lim_axis]);
3088
+    SERIAL_CHAR(AXIS_CHAR(lim_axis));
3049
     SERIAL_ECHOPGM(" Max ");
3089
     SERIAL_ECHOPGM(" Max ");
3050
     SERIAL_ECHOPGM_P(setting_name);
3090
     SERIAL_ECHOPGM_P(setting_name);
3051
     SERIAL_ECHOLNPAIR(" limited to ", val);
3091
     SERIAL_ECHOLNPAIR(" limited to ", val);

+ 33
- 17
Marlin/src/module/planner.h 查看文件

76
 // Feedrate for manual moves
76
 // Feedrate for manual moves
77
 #ifdef MANUAL_FEEDRATE
77
 #ifdef MANUAL_FEEDRATE
78
   constexpr xyze_feedrate_t _mf = MANUAL_FEEDRATE,
78
   constexpr xyze_feedrate_t _mf = MANUAL_FEEDRATE,
79
-                            manual_feedrate_mm_s { _mf.x / 60.0f, _mf.y / 60.0f, _mf.z / 60.0f, _mf.e / 60.0f };
79
+           manual_feedrate_mm_s = LOGICAL_AXIS_ARRAY(_mf.e / 60.0f, _mf.x / 60.0f, _mf.y / 60.0f, _mf.z / 60.0f);
80
 #endif
80
 #endif
81
 
81
 
82
 #if IS_KINEMATIC && HAS_JUNCTION_DEVIATION
82
 #if IS_KINEMATIC && HAS_JUNCTION_DEVIATION
758
      *  extruder    - target extruder
758
      *  extruder    - target extruder
759
      *  millimeters - the length of the movement, if known
759
      *  millimeters - the length of the movement, if known
760
      */
760
      */
761
-    static bool buffer_segment(const_float_t a, const_float_t b, const_float_t c, const_float_t e
761
+    static bool buffer_segment(
762
+      LOGICAL_AXIS_LIST(const_float_t e, const_float_t a, const_float_t b, const_float_t c)
762
       OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
763
       OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
763
       , const_feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters=0.0
764
       , const_feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters=0.0
764
     );
765
     );
767
       OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
768
       OPTARG(HAS_DIST_MM_ARG, const xyze_float_t &cart_dist_mm)
768
       , const_feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters=0.0
769
       , const_feedRate_t fr_mm_s, const uint8_t extruder, const_float_t millimeters=0.0
769
     ) {
770
     ) {
770
-      return buffer_segment(abce.a, abce.b, abce.c, abce.e
771
+      return buffer_segment(
772
+        LOGICAL_AXIS_LIST(abce.e, abce.a, abce.b, abce.c)
771
         OPTARG(HAS_DIST_MM_ARG, cart_dist_mm)
773
         OPTARG(HAS_DIST_MM_ARG, cart_dist_mm)
772
-        , fr_mm_s, extruder, millimeters);
774
+        , fr_mm_s, extruder, millimeters
775
+      );
773
     }
776
     }
774
 
777
 
775
   public:
778
   public:
785
      *  millimeters  - the length of the movement, if known
788
      *  millimeters  - the length of the movement, if known
786
      *  inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
789
      *  inv_duration - the reciprocal if the duration of the movement, if known (kinematic only if feeedrate scaling is enabled)
787
      */
790
      */
788
-    static bool buffer_line(const_float_t rx, const_float_t ry, const_float_t rz, const_float_t e, const_feedRate_t fr_mm_s, const uint8_t extruder, const float millimeters=0.0
791
+    static bool buffer_line(
792
+      LOGICAL_AXIS_LIST(const_float_t e, const_float_t rx, const_float_t ry, const_float_t rz)
793
+      , const feedRate_t &fr_mm_s, const uint8_t extruder, const float millimeters=0.0
789
       OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration=0.0)
794
       OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration=0.0)
790
     );
795
     );
791
 
796
 
792
     FORCE_INLINE static bool buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, const uint8_t extruder, const float millimeters=0.0
797
     FORCE_INLINE static bool buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, const uint8_t extruder, const float millimeters=0.0
793
       OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration=0.0)
798
       OPTARG(SCARA_FEEDRATE_SCALING, const_float_t inv_duration=0.0)
794
     ) {
799
     ) {
795
-      return buffer_line(cart.x, cart.y, cart.z, cart.e, fr_mm_s, extruder, millimeters
800
+      return buffer_line(
801
+        LOGICAL_AXIS_LIST(cart.e, cart.x, cart.y, cart.z)
802
+        , fr_mm_s, extruder, millimeters
796
         OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
803
         OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)
797
       );
804
       );
798
     }
805
     }
814
      *
821
      *
815
      * Clears previous speed values.
822
      * Clears previous speed values.
816
      */
823
      */
817
-    static void set_position_mm(const_float_t rx, const_float_t ry, const_float_t rz, const_float_t e);
818
-    FORCE_INLINE static void set_position_mm(const xyze_pos_t &cart) { set_position_mm(cart.x, cart.y, cart.z, cart.e); }
819
-    static void set_e_position_mm(const_float_t e);
824
+    static void set_position_mm(
825
+      LOGICAL_AXIS_LIST(const_float_t e, const_float_t rx, const_float_t ry, const_float_t rz)
826
+    );
827
+    FORCE_INLINE static void set_position_mm(const xyze_pos_t &cart) {
828
+      set_position_mm(LOGICAL_AXIS_LIST(cart.e, cart.x, cart.y, cart.z, cart.i, cart.j, cart.k));
829
+    }
830
+
831
+    #if HAS_EXTRUDERS
832
+      static void set_e_position_mm(const_float_t e);
833
+    #endif
820
 
834
 
821
     /**
835
     /**
822
      * Set the planner.position and individual stepper positions.
836
      * Set the planner.position and individual stepper positions.
824
      * The supplied position is in machine space, and no additional
838
      * The supplied position is in machine space, and no additional
825
      * conversions are applied.
839
      * conversions are applied.
826
      */
840
      */
827
-    static void set_machine_position_mm(const_float_t a, const_float_t b, const_float_t c, const_float_t e);
828
-    FORCE_INLINE static void set_machine_position_mm(const abce_pos_t &abce) { set_machine_position_mm(abce.a, abce.b, abce.c, abce.e); }
841
+    static void set_machine_position_mm(
842
+      LOGICAL_AXIS_LIST(const_float_t e, const_float_t a, const_float_t b, const_float_t c)
843
+    );
844
+    FORCE_INLINE static void set_machine_position_mm(const abce_pos_t &abce) {
845
+      set_machine_position_mm(LOGICAL_AXIS_LIST(abce.e, abce.a, abce.b, abce.c));
846
+    }
829
 
847
 
830
     /**
848
     /**
831
      * Get an axis position according to stepper position(s)
849
      * Get an axis position according to stepper position(s)
834
     static float get_axis_position_mm(const AxisEnum axis);
852
     static float get_axis_position_mm(const AxisEnum axis);
835
 
853
 
836
     static inline abce_pos_t get_axis_positions_mm() {
854
     static inline abce_pos_t get_axis_positions_mm() {
837
-      const abce_pos_t out = {
838
-        get_axis_position_mm(A_AXIS),
839
-        get_axis_position_mm(B_AXIS),
840
-        get_axis_position_mm(C_AXIS),
841
-        get_axis_position_mm(E_AXIS)
842
-      };
855
+      const abce_pos_t out = LOGICAL_AXIS_ARRAY(
856
+        get_axis_position_mm(E_AXIS),
857
+        get_axis_position_mm(A_AXIS), get_axis_position_mm(B_AXIS), get_axis_position_mm(C_AXIS)
858
+      );
843
       return out;
859
       return out;
844
     }
860
     }
845
 
861
 

+ 26
- 20
Marlin/src/module/settings.cpp 查看文件

168
   void M554_report();
168
   void M554_report();
169
 #endif
169
 #endif
170
 
170
 
171
-typedef struct { uint16_t X, Y, Z, X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7; } tmc_stepper_current_t;
172
-typedef struct { uint32_t X, Y, Z, X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7; } tmc_hybrid_threshold_t;
173
-typedef struct {  int16_t X, Y, Z, X2, Y2, Z2, Z3, Z4;                                 } tmc_sgt_t;
174
-typedef struct {     bool X, Y, Z, X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7; } tmc_stealth_enabled_t;
171
+typedef struct { uint16_t LINEAR_AXIS_LIST(X, Y, Z), X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7; } tmc_stepper_current_t;
172
+typedef struct { uint32_t LINEAR_AXIS_LIST(X, Y, Z), X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7; } tmc_hybrid_threshold_t;
173
+typedef struct {  int16_t LINEAR_AXIS_LIST(X, Y, Z), X2, Y2, Z2, Z3, Z4;                                 } tmc_sgt_t;
174
+typedef struct {     bool LINEAR_AXIS_LIST(X, Y, Z), X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7; } tmc_stealth_enabled_t;
175
 
175
 
176
 // Limit an index to an array size
176
 // Limit an index to an array size
177
 #define ALIM(I,ARR) _MIN(I, (signed)COUNT(ARR) - 1)
177
 #define ALIM(I,ARR) _MIN(I, (signed)COUNT(ARR) - 1)
654
           EEPROM_WRITE(dummyf);
654
           EEPROM_WRITE(dummyf);
655
         #endif
655
         #endif
656
       #else
656
       #else
657
-        const xyze_pos_t planner_max_jerk = { 10, 10, 0.4, float(DEFAULT_EJERK) };
657
+        const xyze_pos_t planner_max_jerk = LOGICAL_AXIS_ARRAY(float(DEFAULT_EJERK), 10, 10, 0.4);
658
         EEPROM_WRITE(planner_max_jerk);
658
         EEPROM_WRITE(planner_max_jerk);
659
       #endif
659
       #endif
660
 
660
 
1188
         #endif
1188
         #endif
1189
       #else
1189
       #else
1190
         const tmc_hybrid_threshold_t tmc_hybrid_threshold = {
1190
         const tmc_hybrid_threshold_t tmc_hybrid_threshold = {
1191
-          .X  = 100, .Y  = 100, .Z  =   3,
1191
+          LINEAR_AXIS_LIST(.X = 100, .Y = 100, .Z = 3),
1192
           .X2 = 100, .Y2 = 100, .Z2 =   3, .Z3 =   3, .Z4 = 3,
1192
           .X2 = 100, .Y2 = 100, .Z2 =   3, .Z3 =   3, .Z4 = 3,
1193
-          .E0 =  30, .E1 =  30, .E2 =  30,
1194
-          .E3 =  30, .E4 =  30, .E5 =  30
1193
+          .E0 =  30, .E1 =  30, .E2 =  30, .E3 =  30,
1194
+          .E4 =  30, .E5 =  30, .E6 =  30, .E7 =  30
1195
         };
1195
         };
1196
       #endif
1196
       #endif
1197
       EEPROM_WRITE(tmc_hybrid_threshold);
1197
       EEPROM_WRITE(tmc_hybrid_threshold);
2604
     #ifndef DEFAULT_ZJERK
2604
     #ifndef DEFAULT_ZJERK
2605
       #define DEFAULT_ZJERK 0
2605
       #define DEFAULT_ZJERK 0
2606
     #endif
2606
     #endif
2607
-    planner.max_jerk.set(DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK);
2607
+    planner.max_jerk.set(LINEAR_AXIS_LIST(DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK));
2608
     TERN_(HAS_CLASSIC_E_JERK, planner.max_jerk.e = DEFAULT_EJERK;);
2608
     TERN_(HAS_CLASSIC_E_JERK, planner.max_jerk.e = DEFAULT_EJERK;);
2609
   #endif
2609
   #endif
2610
 
2610
 
3142
     CONFIG_ECHO_HEADING("Maximum feedrates (units/s):");
3142
     CONFIG_ECHO_HEADING("Maximum feedrates (units/s):");
3143
     CONFIG_ECHO_START();
3143
     CONFIG_ECHO_START();
3144
     SERIAL_ECHOLNPAIR_P(
3144
     SERIAL_ECHOLNPAIR_P(
3145
-        PSTR("  M203 X"), LINEAR_UNIT(planner.settings.max_feedrate_mm_s[X_AXIS])
3146
-      , SP_Y_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Y_AXIS])
3147
-      , SP_Z_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Z_AXIS])
3148
-      #if DISABLED(DISTINCT_E_FACTORS)
3145
+      LIST_N(DOUBLE(LINEAR_AXES),
3146
+        PSTR("  M203 X"), LINEAR_UNIT(planner.settings.max_feedrate_mm_s[X_AXIS]),
3147
+        SP_Y_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Y_AXIS]),
3148
+        SP_Z_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Z_AXIS])
3149
+      )
3150
+      #if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS)
3149
         , SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_feedrate_mm_s[E_AXIS])
3151
         , SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_feedrate_mm_s[E_AXIS])
3150
       #endif
3152
       #endif
3151
     );
3153
     );
3162
     CONFIG_ECHO_HEADING("Maximum Acceleration (units/s2):");
3164
     CONFIG_ECHO_HEADING("Maximum Acceleration (units/s2):");
3163
     CONFIG_ECHO_START();
3165
     CONFIG_ECHO_START();
3164
     SERIAL_ECHOLNPAIR_P(
3166
     SERIAL_ECHOLNPAIR_P(
3165
-        PSTR("  M201 X"), LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[X_AXIS])
3166
-      , SP_Y_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Y_AXIS])
3167
-      , SP_Z_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Z_AXIS])
3168
-      #if DISABLED(DISTINCT_E_FACTORS)
3167
+      LIST_N(DOUBLE(LINEAR_AXES),
3168
+        PSTR("  M201 X"), LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[X_AXIS]),
3169
+        SP_Y_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Y_AXIS]),
3170
+        SP_Z_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Z_AXIS])
3171
+      )
3172
+      #if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS)
3169
         , SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_acceleration_mm_per_s2[E_AXIS])
3173
         , SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_acceleration_mm_per_s2[E_AXIS])
3170
       #endif
3174
       #endif
3171
     );
3175
     );
3894
       CONFIG_ECHO_START();
3898
       CONFIG_ECHO_START();
3895
       SERIAL_ECHOLNPAIR_P(
3899
       SERIAL_ECHOLNPAIR_P(
3896
           PSTR("  M425 F"), backlash.get_correction()
3900
           PSTR("  M425 F"), backlash.get_correction()
3897
-        , SP_X_STR, LINEAR_UNIT(backlash.distance_mm.x)
3898
-        , SP_Y_STR, LINEAR_UNIT(backlash.distance_mm.y)
3899
-        , SP_Z_STR, LINEAR_UNIT(backlash.distance_mm.z)
3901
+        , LIST_N(DOUBLE(LINEAR_AXES),
3902
+            SP_X_STR, LINEAR_UNIT(backlash.distance_mm.x),
3903
+            SP_Y_STR, LINEAR_UNIT(backlash.distance_mm.y),
3904
+            SP_Z_STR, LINEAR_UNIT(backlash.distance_mm.z)
3905
+          )
3900
         #ifdef BACKLASH_SMOOTHING_MM
3906
         #ifdef BACKLASH_SMOOTHING_MM
3901
           , PSTR(" S"), LINEAR_UNIT(backlash.smoothing_mm)
3907
           , PSTR(" S"), LINEAR_UNIT(backlash.smoothing_mm)
3902
         #endif
3908
         #endif

+ 34
- 22
Marlin/src/module/stepper.cpp 查看文件

498
         MIXER_STEPPER_LOOP(j) NORM_E_DIR(j);
498
         MIXER_STEPPER_LOOP(j) NORM_E_DIR(j);
499
         count_direction.e = 1;
499
         count_direction.e = 1;
500
       }
500
       }
501
-    #else
501
+    #elif HAS_EXTRUDERS
502
       if (motor_direction(E_AXIS)) {
502
       if (motor_direction(E_AXIS)) {
503
         REV_E_DIR(stepper_extruder);
503
         REV_E_DIR(stepper_extruder);
504
         count_direction.e = -1;
504
         count_direction.e = -1;
1627
           PAGE_PULSE_PREP(X);
1627
           PAGE_PULSE_PREP(X);
1628
           PAGE_PULSE_PREP(Y);
1628
           PAGE_PULSE_PREP(Y);
1629
           PAGE_PULSE_PREP(Z);
1629
           PAGE_PULSE_PREP(Z);
1630
-          PAGE_PULSE_PREP(E);
1630
+          TERN_(HAS_EXTRUDERS, PAGE_PULSE_PREP(E));
1631
 
1631
 
1632
           page_step_state.segment_steps++;
1632
           page_step_state.segment_steps++;
1633
 
1633
 
1660
           PAGE_PULSE_PREP(X);
1660
           PAGE_PULSE_PREP(X);
1661
           PAGE_PULSE_PREP(Y);
1661
           PAGE_PULSE_PREP(Y);
1662
           PAGE_PULSE_PREP(Z);
1662
           PAGE_PULSE_PREP(Z);
1663
-          PAGE_PULSE_PREP(E);
1663
+          TERN_(HAS_EXTRUDERS, PAGE_PULSE_PREP(E));
1664
 
1664
 
1665
           page_step_state.segment_steps++;
1665
           page_step_state.segment_steps++;
1666
 
1666
 
2103
       #endif
2103
       #endif
2104
 
2104
 
2105
       uint8_t axis_bits = 0;
2105
       uint8_t axis_bits = 0;
2106
-      if (X_MOVE_TEST) SBI(axis_bits, A_AXIS);
2107
-      if (Y_MOVE_TEST) SBI(axis_bits, B_AXIS);
2108
-      if (Z_MOVE_TEST) SBI(axis_bits, C_AXIS);
2109
-      //if (!!current_block->steps.e) SBI(axis_bits, E_AXIS);
2110
-      //if (!!current_block->steps.a) SBI(axis_bits, X_HEAD);
2111
-      //if (!!current_block->steps.b) SBI(axis_bits, Y_HEAD);
2112
-      //if (!!current_block->steps.c) SBI(axis_bits, Z_HEAD);
2106
+      LINEAR_AXIS_CODE(
2107
+        if (X_MOVE_TEST) SBI(axis_bits, A_AXIS),
2108
+        if (Y_MOVE_TEST) SBI(axis_bits, B_AXIS),
2109
+        if (Z_MOVE_TEST) SBI(axis_bits, C_AXIS)
2110
+      );
2111
+      //if (current_block->steps.e) SBI(axis_bits, E_AXIS);
2112
+      //if (current_block->steps.a) SBI(axis_bits, X_HEAD);
2113
+      //if (current_block->steps.b) SBI(axis_bits, Y_HEAD);
2114
+      //if (current_block->steps.c) SBI(axis_bits, Z_HEAD);
2113
       axis_did_move = axis_bits;
2115
       axis_did_move = axis_bits;
2114
 
2116
 
2115
       // No acceleration / deceleration time elapsed so far
2117
       // No acceleration / deceleration time elapsed so far
2606
   #endif
2608
   #endif
2607
 
2609
 
2608
   // Init direction bits for first moves
2610
   // Init direction bits for first moves
2609
-  set_directions((INVERT_X_DIR ? _BV(X_AXIS) : 0)
2610
-               | (INVERT_Y_DIR ? _BV(Y_AXIS) : 0)
2611
-               | (INVERT_Z_DIR ? _BV(Z_AXIS) : 0));
2611
+  set_directions(0
2612
+    LINEAR_AXIS_GANG(
2613
+      | TERN0(INVERT_X_DIR, _BV(X_AXIS)),
2614
+      | TERN0(INVERT_Y_DIR, _BV(Y_AXIS)),
2615
+      | TERN0(INVERT_Z_DIR, _BV(Z_AXIS))
2616
+    )
2617
+  );
2612
 
2618
 
2613
   #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
2619
   #if HAS_MOTOR_CURRENT_SPI || HAS_MOTOR_CURRENT_PWM
2614
     initialized = true;
2620
     initialized = true;
2625
  * This allows get_axis_position_mm to correctly
2631
  * This allows get_axis_position_mm to correctly
2626
  * derive the current XYZ position later on.
2632
  * derive the current XYZ position later on.
2627
  */
2633
  */
2628
-void Stepper::_set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) {
2634
+void Stepper::_set_position(
2635
+  LOGICAL_AXIS_LIST(const int32_t &e, const int32_t &a, const int32_t &b, const int32_t &c)
2636
+) {
2629
   #if CORE_IS_XY
2637
   #if CORE_IS_XY
2630
     // corexy positioning
2638
     // corexy positioning
2631
     // these equations follow the form of the dA and dB equations on https://www.corexy.com/theory.html
2639
     // these equations follow the form of the dA and dB equations on https://www.corexy.com/theory.html
2640
     count_position.set(a - b, b, c);
2648
     count_position.set(a - b, b, c);
2641
   #else
2649
   #else
2642
     // default non-h-bot planning
2650
     // default non-h-bot planning
2643
-    count_position.set(a, b, c);
2651
+    count_position.set(LINEAR_AXIS_LIST(a, b, c));
2644
   #endif
2652
   #endif
2645
-  count_position.e = e;
2653
+  TERN_(HAS_EXTRUDERS, count_position.e = e);
2646
 }
2654
 }
2647
 
2655
 
2648
 /**
2656
 /**
2665
 }
2673
 }
2666
 
2674
 
2667
 // Set the current position in steps
2675
 // Set the current position in steps
2668
-void Stepper::set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) {
2676
+//TODO: Test for LINEAR_AXES >= 4
2677
+void Stepper::set_position(
2678
+  LOGICAL_AXIS_LIST(const int32_t &e, const int32_t &a, const int32_t &b, const int32_t &c)
2679
+) {
2669
   planner.synchronize();
2680
   planner.synchronize();
2670
   const bool was_enabled = suspend();
2681
   const bool was_enabled = suspend();
2671
-  _set_position(a, b, c, e);
2682
+  _set_position(LOGICAL_AXIS_LIST(e, a, b, c));
2672
   if (was_enabled) wake_up();
2683
   if (was_enabled) wake_up();
2673
 }
2684
 }
2674
 
2685
 
2743
     SERIAL_ECHOPAIR_P(PSTR(STR_COUNT_X), pos.x, SP_Y_LBL, pos.y);
2754
     SERIAL_ECHOPAIR_P(PSTR(STR_COUNT_X), pos.x, SP_Y_LBL, pos.y);
2744
   #endif
2755
   #endif
2745
   #if ANY(CORE_IS_XZ, CORE_IS_YZ, DELTA)
2756
   #if ANY(CORE_IS_XZ, CORE_IS_YZ, DELTA)
2746
-    SERIAL_ECHOLNPAIR(" C:", pos.z);
2747
-  #else
2748
-    SERIAL_ECHOLNPAIR_P(SP_Z_LBL, pos.z);
2757
+    SERIAL_ECHOPAIR(" C:", pos.z);
2758
+  #elif LINEAR_AXES >= 3
2759
+    SERIAL_ECHOPAIR_P(SP_Z_LBL, pos.z);
2749
   #endif
2760
   #endif
2761
+  SERIAL_EOL();
2750
 }
2762
 }
2751
 
2763
 
2752
 void Stepper::report_positions() {
2764
 void Stepper::report_positions() {
2903
 
2915
 
2904
           DIR_WAIT_BEFORE();
2916
           DIR_WAIT_BEFORE();
2905
 
2917
 
2906
-          const xyz_byte_t old_dir = { X_DIR_READ(), Y_DIR_READ(), Z_DIR_READ() };
2918
+          const xyz_byte_t old_dir = LINEAR_AXIS_ARRAY(X_DIR_READ(), Y_DIR_READ(), Z_DIR_READ());
2907
 
2919
 
2908
           X_DIR_WRITE(INVERT_X_DIR ^ z_direction);
2920
           X_DIR_WRITE(INVERT_X_DIR ^ z_direction);
2909
           Y_DIR_WRITE(INVERT_Y_DIR ^ z_direction);
2921
           Y_DIR_WRITE(INVERT_Y_DIR ^ z_direction);

+ 12
- 4
Marlin/src/module/stepper.h 查看文件

433
     static int32_t position(const AxisEnum axis);
433
     static int32_t position(const AxisEnum axis);
434
 
434
 
435
     // Set the current position in steps
435
     // Set the current position in steps
436
-    static void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e);
437
-    static inline void set_position(const xyze_long_t &abce) { set_position(abce.a, abce.b, abce.c, abce.e); }
436
+    static void set_position(
437
+      LOGICAL_AXIS_LIST(const int32_t &e, const int32_t &a, const int32_t &b, const int32_t &c)
438
+    );
439
+    static inline void set_position(const xyze_long_t &abce) {
440
+      set_position(LOGICAL_AXIS_LIST(abce.e, abce.a, abce.b, abce.c));
441
+    }
438
     static void set_axis_position(const AxisEnum a, const int32_t &v);
442
     static void set_axis_position(const AxisEnum a, const int32_t &v);
439
 
443
 
440
     // Report the positions of the steppers, in steps
444
     // Report the positions of the steppers, in steps
530
   private:
534
   private:
531
 
535
 
532
     // Set the current position in steps
536
     // Set the current position in steps
533
-    static void _set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e);
534
-    FORCE_INLINE static void _set_position(const abce_long_t &spos) { _set_position(spos.a, spos.b, spos.c, spos.e); }
537
+    static void _set_position(
538
+      LOGICAL_AXIS_LIST(const int32_t &e, const int32_t &a, const int32_t &b, const int32_t &c)
539
+    );
540
+    FORCE_INLINE static void _set_position(const abce_long_t &spos) {
541
+      _set_position(LOGICAL_AXIS_LIST(spos.e, spos.a, spos.b, spos.c));
542
+    }
535
 
543
 
536
     FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t *loops) {
544
     FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t *loops) {
537
       uint32_t timer;
545
       uint32_t timer;

+ 15
- 8
Marlin/src/module/stepper/trinamic.cpp 查看文件

35
 #include <HardwareSerial.h>
35
 #include <HardwareSerial.h>
36
 #include <SPI.h>
36
 #include <SPI.h>
37
 
37
 
38
-enum StealthIndex : uint8_t { STEALTH_AXIS_XY, STEALTH_AXIS_Z, STEALTH_AXIS_E };
38
+enum StealthIndex : uint8_t {
39
+  LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z)
40
+};
39
 #define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE)
41
 #define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE)
40
 
42
 
41
 //   IC = TMC model number
43
 //   IC = TMC model number
351
     #endif
353
     #endif
352
   #endif
354
   #endif
353
 
355
 
354
-  enum TMCAxis : uint8_t { X, Y, Z, X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7, TOTAL };
356
+  enum TMCAxis : uint8_t { LINEAR_AXIS_LIST(X, Y, Z), X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7, TOTAL };
355
 
357
 
356
   void tmc_serial_begin() {
358
   void tmc_serial_begin() {
357
     #if HAS_TMC_HW_SERIAL
359
     #if HAS_TMC_HW_SERIAL
716
 }
718
 }
717
 
719
 
718
 void reset_trinamic_drivers() {
720
 void reset_trinamic_drivers() {
719
-  static constexpr bool stealthchop_by_axis[] = { ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_Z), ENABLED(STEALTHCHOP_E) };
721
+  static constexpr bool stealthchop_by_axis[] = LOGICAL_AXIS_ARRAY(
722
+    ENABLED(STEALTHCHOP_E),
723
+    ENABLED(STEALTHCHOP_XY),
724
+    ENABLED(STEALTHCHOP_XY),
725
+    ENABLED(STEALTHCHOP_Z)
726
+  );
720
 
727
 
721
   #if AXIS_IS_TMC(X)
728
   #if AXIS_IS_TMC(X)
722
-    TMC_INIT(X, STEALTH_AXIS_XY);
729
+    TMC_INIT(X, STEALTH_AXIS_X);
723
   #endif
730
   #endif
724
   #if AXIS_IS_TMC(X2)
731
   #if AXIS_IS_TMC(X2)
725
-    TMC_INIT(X2, STEALTH_AXIS_XY);
732
+    TMC_INIT(X2, STEALTH_AXIS_X);
726
   #endif
733
   #endif
727
   #if AXIS_IS_TMC(Y)
734
   #if AXIS_IS_TMC(Y)
728
-    TMC_INIT(Y, STEALTH_AXIS_XY);
735
+    TMC_INIT(Y, STEALTH_AXIS_Y);
729
   #endif
736
   #endif
730
   #if AXIS_IS_TMC(Y2)
737
   #if AXIS_IS_TMC(Y2)
731
-    TMC_INIT(Y2, STEALTH_AXIS_XY);
738
+    TMC_INIT(Y2, STEALTH_AXIS_Y);
732
   #endif
739
   #endif
733
   #if AXIS_IS_TMC(Z)
740
   #if AXIS_IS_TMC(Z)
734
     TMC_INIT(Z, STEALTH_AXIS_Z);
741
     TMC_INIT(Z, STEALTH_AXIS_Z);
792
         stepperZ4.homing_threshold(CAT(TERN(Z4_SENSORLESS, Z4, Z), _STALL_SENSITIVITY));
799
         stepperZ4.homing_threshold(CAT(TERN(Z4_SENSORLESS, Z4, Z), _STALL_SENSITIVITY));
793
       #endif
800
       #endif
794
     #endif
801
     #endif
795
-  #endif
802
+  #endif // USE SENSORLESS
796
 
803
 
797
   #ifdef TMC_ADV
804
   #ifdef TMC_ADV
798
     TMC_ADV()
805
     TMC_ADV()

+ 8
- 4
buildroot/tests/mega2560 查看文件

171
 # Test Laser features with 12864 LCD
171
 # Test Laser features with 12864 LCD
172
 #
172
 #
173
 restore_configs
173
 restore_configs
174
-opt_set MOTHERBOARD BOARD_RAMPS_14_EFB LCD_LANGUAGE en TEMP_SENSOR_COOLER 1 EXTRUDERS 0 TEMP_SENSOR_1 0 SERIAL_PORT_2 2 \
174
+opt_set MOTHERBOARD BOARD_RAMPS_14_EFB EXTRUDERS 0 LCD_LANGUAGE en TEMP_SENSOR_COOLER 1 TEMP_SENSOR_1 0 SERIAL_PORT_2 2 \
175
         DEFAULT_AXIS_STEPS_PER_UNIT '{ 80, 80, 400 }' \
175
         DEFAULT_AXIS_STEPS_PER_UNIT '{ 80, 80, 400 }' \
176
         DEFAULT_MAX_FEEDRATE '{ 300, 300, 5 }' \
176
         DEFAULT_MAX_FEEDRATE '{ 300, 300, 5 }' \
177
-        DEFAULT_MAX_ACCELERATION '{ 3000, 3000, 100 }'
177
+        DEFAULT_MAX_ACCELERATION '{ 3000, 3000, 100 }' \
178
+        MANUAL_FEEDRATE '{ 50*60, 50*60, 4*60 }' \
179
+        AXIS_RELATIVE_MODES '{ false, false, false }'
178
 opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \
180
 opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \
179
            LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER MEATPACK_ON_SERIAL_PORT_1
181
            LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER MEATPACK_ON_SERIAL_PORT_1
180
 
182
 
184
 # Test Laser features with 44780 LCD
186
 # Test Laser features with 44780 LCD
185
 #
187
 #
186
 restore_configs
188
 restore_configs
187
-opt_set MOTHERBOARD BOARD_RAMPS_14_EFB LCD_LANGUAGE en TEMP_SENSOR_COOLER 1 EXTRUDERS 0 TEMP_SENSOR_1 0 \
189
+opt_set MOTHERBOARD BOARD_RAMPS_14_EFB EXTRUDERS 0 LCD_LANGUAGE en TEMP_SENSOR_COOLER 1 TEMP_SENSOR_1 0 \
188
         DEFAULT_AXIS_STEPS_PER_UNIT '{ 80, 80, 400 }' \
190
         DEFAULT_AXIS_STEPS_PER_UNIT '{ 80, 80, 400 }' \
189
         DEFAULT_MAX_FEEDRATE '{ 300, 300, 5 }' \
191
         DEFAULT_MAX_FEEDRATE '{ 300, 300, 5 }' \
190
-        DEFAULT_MAX_ACCELERATION '{ 3000, 3000, 100 }'
192
+        DEFAULT_MAX_ACCELERATION '{ 3000, 3000, 100 }' \
193
+        MANUAL_FEEDRATE '{ 50*60, 50*60, 4*60 }' \
194
+        AXIS_RELATIVE_MODES '{ false, false, false }'
191
 opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \
195
 opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \
192
            LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER
196
            LASER_FEATURE AIR_EVACUATION AIR_EVACUATION_PIN AIR_ASSIST AIR_ASSIST_PIN LASER_COOLANT_FLOW_METER
193
 
197
 

+ 2
- 0
buildroot/tests/rambo 查看文件

48
         DEFAULT_AXIS_STEPS_PER_UNIT '{ 80, 80, 4000 }' \
48
         DEFAULT_AXIS_STEPS_PER_UNIT '{ 80, 80, 4000 }' \
49
         DEFAULT_MAX_FEEDRATE '{ 300, 300, 5 }' \
49
         DEFAULT_MAX_FEEDRATE '{ 300, 300, 5 }' \
50
         DEFAULT_MAX_ACCELERATION '{ 3000, 3000, 100 }' \
50
         DEFAULT_MAX_ACCELERATION '{ 3000, 3000, 100 }' \
51
+        MANUAL_FEEDRATE '{ 50*60, 50*60, 4*60 }' \
51
         AXIS_RELATIVE_MODES '{ false, false, false }' \
52
         AXIS_RELATIVE_MODES '{ false, false, false }' \
52
         LEVEL_CORNERS_LEVELING_ORDER '{ LF, RF }'
53
         LEVEL_CORNERS_LEVELING_ORDER '{ LF, RF }'
53
 opt_enable USE_XMAX_PLUG USE_YMAX_PLUG USE_ZMAX_PLUG \
54
 opt_enable USE_XMAX_PLUG USE_YMAX_PLUG USE_ZMAX_PLUG \
66
         DEFAULT_AXIS_STEPS_PER_UNIT '{ 80, 80, 4000 }' \
67
         DEFAULT_AXIS_STEPS_PER_UNIT '{ 80, 80, 4000 }' \
67
         DEFAULT_MAX_FEEDRATE '{ 300, 300, 5 }' \
68
         DEFAULT_MAX_FEEDRATE '{ 300, 300, 5 }' \
68
         DEFAULT_MAX_ACCELERATION '{ 3000, 3000, 100 }' \
69
         DEFAULT_MAX_ACCELERATION '{ 3000, 3000, 100 }' \
70
+        MANUAL_FEEDRATE '{ 50*60, 50*60, 4*60 }' \
69
         AXIS_RELATIVE_MODES '{ false, false, false }'
71
         AXIS_RELATIVE_MODES '{ false, false, false }'
70
 opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
72
 opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
71
 exec_test $1 $2 "Rambo heated bed only" "$3"
73
 exec_test $1 $2 "Rambo heated bed only" "$3"

正在加载...
取消
保存