@@ -401,19 +401,48 @@ void menu_move() {
401
401
402
402
#endif // HAS_DYNAMIC_FREQ
403
403
404
+ // Suppress warning about storing a stack address in a static string pointer
405
+ #pragma GCC diagnostic push
406
+ #pragma GCC diagnostic ignored "-Wdangling-pointer"
407
+
408
+ #if ALL(__AVR__, HAS_MARLINUI_U8GLIB) && DISABLED(REDUCE_CODE_SIZE_FOR_FT_MOTION_ON_AVR)
409
+ #define CACHE_PREV_STRING
410
+ #endif
411
+
404
412
void menu_ft_motion () {
405
413
// Define stuff ahead of the menu loop
406
- MString<20 > shaper_name[NUM_AXES_SHAPED] {};
407
- #if HAS_X_AXIS
408
- for (uint_fast8_t a = X_AXIS; a < NUM_AXES_SHAPED; ++a)
409
- shaper_name[a] = get_shaper_name (AxisEnum (a));
410
- #endif
411
- #if HAS_DYNAMIC_FREQ
412
- MString<20 > dmode = get_dyn_freq_mode_name ();
413
- #endif
414
-
415
414
ft_config_t &c = ftMotion.cfg ;
416
415
416
+ #ifdef __AVR__
417
+ // Copy Flash strings to RAM for C-string substitution
418
+ // For U8G paged rendering check and skip extra string copy
419
+ #if HAS_X_AXIS
420
+ MString<20 > shaper_name;
421
+ TERN_ (CACHE_PREV_STRING, int8_t prev_a = -1 );
422
+ auto _shaper_name = [&](const AxisEnum a) {
423
+ if (TERN1 (CACHE_PREV_STRING, a != prev_a)) {
424
+ TERN_ (CACHE_PREV_STRING, prev_a = a);
425
+ shaper_name = get_shaper_name (a);
426
+ }
427
+ return shaper_name;
428
+ };
429
+ #endif
430
+ #if HAS_DYNAMIC_FREQ
431
+ MString<20 > dmode;
432
+ TERN_ (CACHE_PREV_STRING, bool got_d = false );
433
+ auto _dmode = [&]{
434
+ if (TERN1 (CACHE_PREV_STRING, !got_d)) {
435
+ TERN_ (CACHE_PREV_STRING, got_d = true );
436
+ dmode = get_dyn_freq_mode_name ();
437
+ }
438
+ return dmode;
439
+ };
440
+ #endif
441
+ #else
442
+ auto _shaper_name = [](const AxisEnum a) { return get_shaper_name (a); };
443
+ auto _dmode = []{ return get_dyn_freq_mode_name (); };
444
+ #endif
445
+
417
446
START_MENU ();
418
447
BACK_ITEM (MSG_MOTION);
419
448
@@ -426,7 +455,7 @@ void menu_move() {
426
455
// Show only when FT Motion is active (or optionally always show)
427
456
if (c.active || ENABLED (FT_MOTION_NO_MENU_TOGGLE)) {
428
457
#if HAS_X_AXIS
429
- SUBMENU_N_S (X_AXIS, shaper_name[ X_AXIS] , MSG_FTM_CMPN_MODE, menu_ftm_shaper_x);
458
+ SUBMENU_N_S (X_AXIS, _shaper_name ( X_AXIS) , MSG_FTM_CMPN_MODE, menu_ftm_shaper_x);
430
459
431
460
if (AXIS_HAS_SHAPER (X)) {
432
461
EDIT_ITEM_FAST_N (float42_52, X_AXIS, MSG_FTM_BASE_FREQ_N, &c.baseFreq .x , FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2 , ftMotion.update_shaping_params );
@@ -436,7 +465,7 @@ void menu_move() {
436
465
}
437
466
#endif
438
467
#if HAS_Y_AXIS
439
- SUBMENU_N_S (Y_AXIS, shaper_name[ Y_AXIS] , MSG_FTM_CMPN_MODE, menu_ftm_shaper_y);
468
+ SUBMENU_N_S (Y_AXIS, _shaper_name ( Y_AXIS) , MSG_FTM_CMPN_MODE, menu_ftm_shaper_y);
440
469
441
470
if (AXIS_HAS_SHAPER (Y)) {
442
471
EDIT_ITEM_FAST_N (float42_52, Y_AXIS, MSG_FTM_BASE_FREQ_N, &c.baseFreq .y , FTM_MIN_SHAPE_FREQ, (FTM_FS) / 2 , ftMotion.update_shaping_params );
@@ -447,7 +476,7 @@ void menu_move() {
447
476
#endif
448
477
449
478
#if HAS_DYNAMIC_FREQ
450
- SUBMENU_S (dmode , MSG_FTM_DYN_MODE, menu_ftm_dyn_mode);
479
+ SUBMENU_S (_dmode () , MSG_FTM_DYN_MODE, menu_ftm_dyn_mode);
451
480
if (c.dynFreqMode != dynFreqMode_DISABLED) {
452
481
#if HAS_X_AXIS
453
482
EDIT_ITEM_FAST_N (float42_52, X_AXIS, MSG_FTM_DFREQ_K_N, &c.dynFreqK .x , 0 .0f , 20 .0f );
@@ -469,13 +498,34 @@ void menu_move() {
469
498
470
499
void menu_tune_ft_motion () {
471
500
// Define stuff ahead of the menu loop
472
- MString<20 > shaper_name[NUM_AXES_SHAPED] {};
473
- #if HAS_X_AXIS
474
- for (uint_fast8_t a = X_AXIS; a < NUM_AXES_SHAPED; ++a)
475
- shaper_name[a] = get_shaper_name (AxisEnum (a));
476
- #endif
477
- #if HAS_DYNAMIC_FREQ
478
- MString<20 > dmode = get_dyn_freq_mode_name ();
501
+ #ifdef __AVR__
502
+ // Copy Flash strings to RAM for C-string substitution
503
+ // For U8G paged rendering check and skip extra string copy
504
+ #if HAS_X_AXIS
505
+ MString<20 > shaper_name;
506
+ TERN_ (CACHE_PREV_STRING, int8_t prev_a = -1 );
507
+ auto _shaper_name = [&](const AxisEnum a) {
508
+ if (TERN1 (CACHE_PREV_STRING, a != prev_a)) {
509
+ TERN_ (CACHE_PREV_STRING, prev_a = a);
510
+ shaper_name = get_shaper_name (a);
511
+ }
512
+ return shaper_name;
513
+ };
514
+ #endif
515
+ #if HAS_DYNAMIC_FREQ
516
+ MString<20 > dmode;
517
+ TERN_ (CACHE_PREV_STRING, bool got_d = false );
518
+ auto _dmode = [&]{
519
+ if (TERN1 (CACHE_PREV_STRING, !got_d)) {
520
+ TERN_ (CACHE_PREV_STRING, got_d = true );
521
+ dmode = get_dyn_freq_mode_name ();
522
+ }
523
+ return dmode;
524
+ };
525
+ #endif
526
+ #else
527
+ auto _shaper_name = [](const AxisEnum a) { return get_shaper_name (a); };
528
+ auto _dmode = []{ return get_dyn_freq_mode_name (); };
479
529
#endif
480
530
481
531
#if HAS_EXTRUDERS
@@ -486,13 +536,13 @@ void menu_move() {
486
536
BACK_ITEM (MSG_TUNE);
487
537
488
538
#if HAS_X_AXIS
489
- SUBMENU_N_S (X_AXIS, shaper_name[ X_AXIS] , MSG_FTM_CMPN_MODE, menu_ftm_shaper_x);
539
+ SUBMENU_N_S (X_AXIS, _shaper_name ( X_AXIS) , MSG_FTM_CMPN_MODE, menu_ftm_shaper_x);
490
540
#endif
491
541
#if HAS_Y_AXIS
492
- SUBMENU_N_S (Y_AXIS, shaper_name[ Y_AXIS] , MSG_FTM_CMPN_MODE, menu_ftm_shaper_y);
542
+ SUBMENU_N_S (Y_AXIS, _shaper_name ( Y_AXIS) , MSG_FTM_CMPN_MODE, menu_ftm_shaper_y);
493
543
#endif
494
544
#if HAS_DYNAMIC_FREQ
495
- SUBMENU_S (dmode , MSG_FTM_DYN_MODE, menu_ftm_dyn_mode);
545
+ SUBMENU_S (_dmode () , MSG_FTM_DYN_MODE, menu_ftm_dyn_mode);
496
546
#endif
497
547
#if HAS_EXTRUDERS
498
548
EDIT_ITEM (bool , MSG_LINEAR_ADVANCE, &c.linearAdvEna );
@@ -503,6 +553,8 @@ void menu_move() {
503
553
END_MENU ();
504
554
}
505
555
556
+ #pragma GCC diagnostic pop
557
+
506
558
#endif // FT_MOTION_MENU
507
559
508
560
void menu_motion () {
0 commit comments