28
28
#include " ../../../module/ft_motion.h"
29
29
#include " ../../../module/stepper.h"
30
30
31
+ void say_shaper_type (const AxisEnum a) {
32
+ SERIAL_ECHOPGM (" axis " );
33
+ switch (ftMotion.cfg .shaper [a]) {
34
+ default : break ;
35
+ case ftMotionShaper_ZV: SERIAL_ECHOPGM (" ZV" ); break ;
36
+ case ftMotionShaper_ZVD: SERIAL_ECHOPGM (" ZVD" ); break ;
37
+ case ftMotionShaper_ZVDD: SERIAL_ECHOPGM (" ZVDD" ); break ;
38
+ case ftMotionShaper_ZVDDD: SERIAL_ECHOPGM (" ZVDDD" ); break ;
39
+ case ftMotionShaper_EI: SERIAL_ECHOPGM (" EI" ); break ;
40
+ case ftMotionShaper_2HEI: SERIAL_ECHOPGM (" 2 Hump EI" ); break ;
41
+ case ftMotionShaper_3HEI: SERIAL_ECHOPGM (" 3 Hump EI" ); break ;
42
+ case ftMotionShaper_MZV: SERIAL_ECHOPGM (" MZV" ); break ;
43
+ }
44
+ SERIAL_ECHOPGM (" shaping" );
45
+ }
46
+
47
+ #if CORE_IS_XY || CORE_IS_XZ
48
+ #define AXIS_0_NAME " A"
49
+ #else
50
+ #define AXIS_0_NAME " X"
51
+ #endif
52
+ #if CORE_IS_XY || CORE_IS_YZ
53
+ #define AXIS_1_NAME " B"
54
+ #else
55
+ #define AXIS_1_NAME " Y"
56
+ #endif
57
+
31
58
void say_shaping () {
32
59
// FT Enabled
33
- SERIAL_ECHO_TERNARY (ftMotion.cfg .mode , " Fixed-Time Motion " , " en" , " dis" , " abled" );
60
+ SERIAL_ECHO_TERNARY (ftMotion.cfg .active , " Fixed-Time Motion " , " en" , " dis" , " abled" );
34
61
35
62
// FT Shaping
36
63
#if HAS_X_AXIS
37
- if (ftMotion.cfg .mode > ftMotionMode_ENABLED) {
38
- SERIAL_ECHOPGM (" with " );
39
- switch (ftMotion.cfg .mode ) {
40
- default : break ;
41
- case ftMotionMode_ZV: SERIAL_ECHOPGM (" ZV" ); break ;
42
- case ftMotionMode_ZVD: SERIAL_ECHOPGM (" ZVD" ); break ;
43
- case ftMotionMode_ZVDD: SERIAL_ECHOPGM (" ZVDD" ); break ;
44
- case ftMotionMode_ZVDDD: SERIAL_ECHOPGM (" ZVDDD" ); break ;
45
- case ftMotionMode_EI: SERIAL_ECHOPGM (" EI" ); break ;
46
- case ftMotionMode_2HEI: SERIAL_ECHOPGM (" 2 Hump EI" ); break ;
47
- case ftMotionMode_3HEI: SERIAL_ECHOPGM (" 3 Hump EI" ); break ;
48
- case ftMotionMode_MZV: SERIAL_ECHOPGM (" MZV" ); break ;
49
- // case ftMotionMode_DISCTF: SERIAL_ECHOPGM("discrete transfer functions"); break;
50
- // case ftMotionMode_ULENDO_FBS: SERIAL_ECHOPGM("Ulendo FBS."); return;
51
- }
52
- SERIAL_ECHOPGM (" shaping" );
64
+ if (CMPNSTR_HAS_SHAPER (X_AXIS)) {
65
+ SERIAL_ECHOPGM (" with " AXIS_0_NAME);
66
+ say_shaper_type (X_AXIS);
67
+ }
68
+ #endif
69
+ #if HAS_Y_AXIS
70
+ if (CMPNSTR_HAS_SHAPER (Y_AXIS)) {
71
+ SERIAL_ECHOPGM (" and with " AXIS_1_NAME);
72
+ say_shaper_type (Y_AXIS);
53
73
}
54
74
#endif
75
+
55
76
SERIAL_ECHOLNPGM (" ." );
56
77
57
78
const bool z_based = TERN0 (HAS_DYNAMIC_FREQ_MM, ftMotion.cfg .dynFreqMode == dynFreqMode_Z_BASED),
58
79
g_based = TERN0 (HAS_DYNAMIC_FREQ_G, ftMotion.cfg .dynFreqMode == dynFreqMode_MASS_BASED),
59
80
dynamic = z_based || g_based;
60
81
61
82
// FT Dynamic Frequency Mode
62
- if (ftMotion. cfg . modeHasShaper ( )) {
83
+ if (CMPNSTR_HAS_SHAPER (X_AXIS) || CMPNSTR_HAS_SHAPER (Y_AXIS )) {
63
84
#if HAS_DYNAMIC_FREQ
64
85
SERIAL_ECHOPGM (" Dynamic Frequency Mode " );
65
86
switch (ftMotion.cfg .dynFreqMode ) {
@@ -76,7 +97,7 @@ void say_shaping() {
76
97
#endif
77
98
78
99
#if HAS_X_AXIS
79
- SERIAL_ECHO_TERNARY (dynamic, " X/A " , " base dynamic" , " static" , " compensator frequency: " );
100
+ SERIAL_ECHO_TERNARY (dynamic, AXIS_0_NAME " " , " base dynamic" , " static" , " shaper frequency: " );
80
101
SERIAL_ECHO (p_float_t (ftMotion.cfg .baseFreq [X_AXIS], 2 ), F (" Hz" ));
81
102
#if HAS_DYNAMIC_FREQ
82
103
if (dynamic) SERIAL_ECHO (F (" scaling: " ), p_float_t (ftMotion.cfg .dynFreqK [X_AXIS], 2 ), F (" Hz/" ), z_based ? F (" mm" ) : F (" g" ));
@@ -85,7 +106,7 @@ void say_shaping() {
85
106
#endif
86
107
87
108
#if HAS_Y_AXIS
88
- SERIAL_ECHO_TERNARY (dynamic, " Y/B " , " base dynamic" , " static" , " compensator frequency: " );
109
+ SERIAL_ECHO_TERNARY (dynamic, AXIS_1_NAME " " , " base dynamic" , " static" , " shaper frequency: " );
89
110
SERIAL_ECHO (p_float_t (ftMotion.cfg .baseFreq [Y_AXIS], 2 ), F (" Hz" ));
90
111
#if HAS_DYNAMIC_FREQ
91
112
if (dynamic) SERIAL_ECHO (F (" scaling: " ), p_float_t (ftMotion.cfg .dynFreqK [Y_AXIS], 2 ), F (" Hz/" ), z_based ? F (" mm" ) : F (" g" ));
@@ -108,7 +129,7 @@ void GcodeSuite::M493_report(const bool forReplay/*=true*/) {
108
129
109
130
report_heading_etc (forReplay, F (STR_FT_MOTION));
110
131
const ft_config_t &c = ftMotion.cfg ;
111
- SERIAL_ECHOPGM (" M493 S" , c.mode );
132
+ SERIAL_ECHOPGM (" M493 S" , c.active );
112
133
#if HAS_X_AXIS
113
134
SERIAL_ECHOPGM (" A" , c.baseFreq [X_AXIS]);
114
135
#if HAS_Y_AXIS
@@ -133,18 +154,21 @@ void GcodeSuite::M493_report(const bool forReplay/*=true*/) {
133
154
/* *
134
155
* M493: Set Fixed-time Motion Control parameters
135
156
*
136
- * S<mode> Set the motion / shaping mode. Shaping requires an X axis, at the minimum.
157
+ * S<bool> Set Fixed-Time motion mode on or off.
158
+ * 0: Fixed-Time Motion OFF (Standard Motion)
159
+ * 1: Fixed-Time Motion ON
137
160
*
138
- * 0: Standard Motion
139
- * 1: Fixed-Time Motion
140
- * 10: ZV : Zero Vibration
141
- * 11: ZVD : Zero Vibration and Derivative
142
- * 12: ZVDD : Zero Vibration, Derivative, and Double Derivative
143
- * 13: ZVDDD : Zero Vibration, Derivative, Double Derivative, and Triple Derivative
144
- * 14: EI : Extra-Intensive
145
- * 15: 2HEI : 2-Hump Extra-Intensive
146
- * 16: 3HEI : 3-Hump Extra-Intensive
147
- * 17: MZV : Mass-based Zero Vibration
161
+ * X/Y<mode> Set the vibration compensator [input shaper] mode for X / Y axis.
162
+ * Users / slicers must remember to set the mode for both axes!
163
+ * 0: NONE : No input shaper
164
+ * 1: ZV : Zero Vibration
165
+ * 2: ZVD : Zero Vibration and Derivative
166
+ * 3: ZVDD : Zero Vibration, Derivative, and Double Derivative
167
+ * 4: ZVDDD : Zero Vibration, Derivative, Double Derivative, and Triple Derivative
168
+ * 5: EI : Extra-Intensive
169
+ * 6: 2HEI : 2-Hump Extra-Intensive
170
+ * 7: 3HEI : 3-Hump Extra-Intensive
171
+ * 8: MZV : Mass-based Zero Vibration
148
172
*
149
173
* P<bool> Enable (1) or Disable (0) Linear Advance pressure control
150
174
*
@@ -166,40 +190,56 @@ void GcodeSuite::M493_report(const bool forReplay/*=true*/) {
166
190
* R 0.00 Set the vibration tolerance for the Y axis
167
191
*/
168
192
void GcodeSuite::M493 () {
169
- struct { bool update_n: 1 , update_a :1 , reset_ft:1 , report_h:1 ; } flag = { false };
193
+ struct { bool update :1 , reset_ft:1 , report_h:1 ; } flag = { false };
170
194
171
195
if (!parser.seen_any ())
172
196
flag.report_h = true ;
173
197
174
198
// Parse 'S' mode parameter.
175
- if (parser.seenval (' S' )) {
176
- const ftMotionMode_t newmm = (ftMotionMode_t)parser.value_byte ();
177
-
178
- if (newmm != ftMotion.cfg .mode ) {
179
- switch (newmm) {
180
- default : SERIAL_ECHOLNPGM (" ?Invalid control mode [S] value." ); return ;
181
- #if HAS_X_AXIS
182
- case ftMotionMode_ZV:
183
- case ftMotionMode_ZVD:
184
- case ftMotionMode_ZVDD:
185
- case ftMotionMode_ZVDDD:
186
- case ftMotionMode_EI:
187
- case ftMotionMode_2HEI:
188
- case ftMotionMode_3HEI:
189
- case ftMotionMode_MZV:
190
- // case ftMotionMode_ULENDO_FBS:
191
- // case ftMotionMode_DISCTF:
192
- flag.update_n = flag.update_a = true ;
193
- #endif
194
- case ftMotionMode_DISABLED: flag.reset_ft = true ;
195
- case ftMotionMode_ENABLED:
196
- ftMotion.cfg .mode = newmm;
197
- flag.report_h = true ;
199
+ if (parser.seen (' S' )) {
200
+ const bool active = parser.value_bool ();
201
+
202
+ if (active != ftMotion.cfg .active ) {
203
+ switch (active) {
204
+ case false : flag.reset_ft = true ;
205
+ case true : flag.report_h = true ;
206
+ ftMotion.cfg .active = active;
198
207
break ;
199
208
}
200
209
}
201
210
}
202
211
212
+ #if HAS_X_AXIS
213
+ auto set_shaper = [&](const AxisEnum axis, const char c) {
214
+ const ftMotionShaper_t newsh = (ftMotionShaper_t)parser.value_byte ();
215
+ if (newsh != ftMotion.cfg .shaper [axis]) {
216
+ switch (newsh) {
217
+ default : SERIAL_ECHOLNPGM (" ?Invalid [" , C (c), " ] shaper." ); return true ;
218
+ case ftMotionShaper_NONE:
219
+ case ftMotionShaper_ZV:
220
+ case ftMotionShaper_ZVD:
221
+ case ftMotionShaper_ZVDD:
222
+ case ftMotionShaper_ZVDDD:
223
+ case ftMotionShaper_EI:
224
+ case ftMotionShaper_2HEI:
225
+ case ftMotionShaper_3HEI:
226
+ case ftMotionShaper_MZV:
227
+ ftMotion.cfg .shaper [axis] = newsh;
228
+ flag.update = flag.report_h = true ;
229
+ break ;
230
+ }
231
+ }
232
+ return false ;
233
+ };
234
+
235
+ if (parser.seenval (' X' ) && set_shaper (X_AXIS, ' X' )) return ; // Parse 'X' mode parameter
236
+
237
+ #if HAS_Y_AXIS
238
+ if (parser.seenval (' Y' ) && set_shaper (Y_AXIS, ' Y' )) return ; // Parse 'Y' mode parameter
239
+ #endif
240
+
241
+ #endif // HAS_X_AXIS
242
+
203
243
#if HAS_EXTRUDERS
204
244
205
245
// Pressure control (linear advance) parameter.
@@ -227,7 +267,7 @@ void GcodeSuite::M493() {
227
267
228
268
// Dynamic frequency mode parameter.
229
269
if (parser.seenval (' D' )) {
230
- if (ftMotion. cfg . modeHasShaper ( )) {
270
+ if (CMPNSTR_HAS_SHAPER (X_AXIS) || CMPNSTR_HAS_SHAPER (Y_AXIS )) {
231
271
const dynFreqMode_t val = dynFreqMode_t (parser.value_byte ());
232
272
switch (val) {
233
273
#if HAS_DYNAMIC_FREQ_MM
@@ -261,12 +301,12 @@ void GcodeSuite::M493() {
261
301
262
302
// Parse frequency parameter (X axis).
263
303
if (parser.seenval (' A' )) {
264
- if (ftMotion. cfg . modeHasShaper ( )) {
304
+ if (CMPNSTR_HAS_SHAPER (X_AXIS )) {
265
305
const float val = parser.value_float ();
266
306
// TODO: Frequency minimum is dependent on the shaper used; the above check isn't always correct.
267
307
if (WITHIN (val, FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2 )) {
268
308
ftMotion.cfg .baseFreq [X_AXIS] = val;
269
- flag.update_n = flag.reset_ft = flag.report_h = true ;
309
+ flag.update = flag.reset_ft = flag.report_h = true ;
270
310
}
271
311
else // Frequency out of range.
272
312
SERIAL_ECHOLNPGM (" Invalid [" , C (' A' ), " ] frequency value." );
@@ -290,10 +330,10 @@ void GcodeSuite::M493() {
290
330
// Parse zeta parameter (X axis).
291
331
if (parser.seenval (' I' )) {
292
332
const float val = parser.value_float ();
293
- if (ftMotion. cfg . modeHasShaper ( )) {
333
+ if (CMPNSTR_HAS_SHAPER (X_AXIS )) {
294
334
if (WITHIN (val, 0 .01f , 1 .0f )) {
295
335
ftMotion.cfg .zeta [0 ] = val;
296
- flag.update_n = flag. update_a = true ;
336
+ flag.update = true ;
297
337
}
298
338
else
299
339
SERIAL_ECHOLNPGM (" Invalid X zeta [" , C (' I' ), " ] value." ); // Zeta out of range.
@@ -305,10 +345,10 @@ void GcodeSuite::M493() {
305
345
// Parse vtol parameter (X axis).
306
346
if (parser.seenval (' Q' )) {
307
347
const float val = parser.value_float ();
308
- if (ftMotion. cfg . modeHasShaper () && IS_EI_MODE (ftMotion. cfg . mode )) {
348
+ if (CMPNSTR_IS_EISHAPER (X_AXIS )) {
309
349
if (WITHIN (val, 0 .00f , 1 .0f )) {
310
350
ftMotion.cfg .vtol [0 ] = val;
311
- flag.update_a = true ;
351
+ flag.update = true ;
312
352
}
313
353
else
314
354
SERIAL_ECHOLNPGM (" Invalid X vtol [" , C (' Q' ), " ] value." ); // VTol out of range.
@@ -323,11 +363,11 @@ void GcodeSuite::M493() {
323
363
324
364
// Parse frequency parameter (Y axis).
325
365
if (parser.seenval (' B' )) {
326
- if (ftMotion. cfg . modeHasShaper ( )) {
366
+ if (CMPNSTR_HAS_SHAPER (Y_AXIS )) {
327
367
const float val = parser.value_float ();
328
368
if (WITHIN (val, FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2 )) {
329
369
ftMotion.cfg .baseFreq [Y_AXIS] = val;
330
- flag.update_n = flag.reset_ft = flag.report_h = true ;
370
+ flag.update = flag.reset_ft = flag.report_h = true ;
331
371
}
332
372
else // Frequency out of range.
333
373
SERIAL_ECHOLNPGM (" Invalid frequency [" , C (' B' ), " ] value." );
@@ -351,10 +391,10 @@ void GcodeSuite::M493() {
351
391
// Parse zeta parameter (Y axis).
352
392
if (parser.seenval (' J' )) {
353
393
const float val = parser.value_float ();
354
- if (ftMotion. cfg . modeHasShaper ( )) {
394
+ if (CMPNSTR_HAS_SHAPER (Y_AXIS )) {
355
395
if (WITHIN (val, 0 .01f , 1 .0f )) {
356
396
ftMotion.cfg .zeta [1 ] = val;
357
- flag.update_n = flag. update_a = true ;
397
+ flag.update = true ;
358
398
}
359
399
else
360
400
SERIAL_ECHOLNPGM (" Invalid Y zeta [" , C (' J' ), " ] value." ); // Zeta Out of range
@@ -366,10 +406,10 @@ void GcodeSuite::M493() {
366
406
// Parse vtol parameter (Y axis).
367
407
if (parser.seenval (' R' )) {
368
408
const float val = parser.value_float ();
369
- if (ftMotion. cfg . modeHasShaper () && IS_EI_MODE (ftMotion. cfg . mode )) {
409
+ if (CMPNSTR_IS_EISHAPER (Y_AXIS )) {
370
410
if (WITHIN (val, 0 .00f , 1 .0f )) {
371
411
ftMotion.cfg .vtol [1 ] = val;
372
- flag.update_a = true ;
412
+ flag.update = true ;
373
413
}
374
414
else
375
415
SERIAL_ECHOLNPGM (" Invalid Y vtol [" , C (' R' ), " ] value." ); // VTol out of range.
@@ -382,9 +422,7 @@ void GcodeSuite::M493() {
382
422
383
423
planner.synchronize ();
384
424
385
- if (flag.update_n ) ftMotion.refreshShapingN ();
386
-
387
- if (flag.update_a ) ftMotion.updateShapingA ();
425
+ if (flag.update ) ftMotion.update_shaping_params ();
388
426
389
427
if (flag.reset_ft ) {
390
428
stepper.ftMotion_syncPosition ();
0 commit comments