Skip to content

Commit eae339b

Browse files
tombrazierthinkyhead
authored andcommitted
⚡️ Better IS buffer size calc (MarlinFirmware#25035)
1 parent 79b8847 commit eae339b

File tree

4 files changed

+53
-53
lines changed

4 files changed

+53
-53
lines changed

Marlin/Configuration_adv.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,14 +1063,13 @@
10631063
*
10641064
* Zero Vibration (ZV) Input Shaping for X and/or Y movements.
10651065
*
1066-
* This option uses a lot of SRAM for the step buffer, which is related to the
1067-
* largest step rate possible for the shaped axes. If the build fails due to
1068-
* low SRAM the buffer size may be reduced by setting smaller values for
1069-
* DEFAULT_AXIS_STEPS_PER_UNIT and/or DEFAULT_MAX_FEEDRATE. Disabling
1070-
* ADAPTIVE_STEP_SMOOTHING and reducing the step rate for non-shaped axes may
1071-
* also reduce the buffer sizes. Runtime editing of max feedrate (M203) or
1072-
* resonant frequency (M593) may result in input shaping losing effectiveness
1073-
* during high speed movements to prevent buffer overruns.
1066+
* This option uses a lot of SRAM for the step buffer. The buffer size is
1067+
* calculated automatically from SHAPING_FREQ_[XY], DEFAULT_AXIS_STEPS_PER_UNIT,
1068+
* DEFAULT_MAX_FEEDRATE and ADAPTIVE_STEP_SMOOTHING. The default calculation can
1069+
* be overridden by setting SHAPING_MIN_FREQ and/or SHAPING_MAX_FEEDRATE.
1070+
* The higher the frequency and the lower the feedrate, the smaller the buffer.
1071+
* If the buffer is too small at runtime, input shaping will have reduced
1072+
* effectiveness during high speed movements.
10741073
*
10751074
* Tune with M593 D<factor> F<frequency>:
10761075
*
@@ -1084,14 +1083,16 @@
10841083
//#define INPUT_SHAPING_Y
10851084
#if EITHER(INPUT_SHAPING_X, INPUT_SHAPING_Y)
10861085
#if ENABLED(INPUT_SHAPING_X)
1087-
#define SHAPING_FREQ_X 40 // (Hz) The default dominant resonant frequency on the X axis.
1088-
#define SHAPING_ZETA_X 0.15f // Damping ratio of the X axis (range: 0.0 = no damping to 1.0 = critical damping).
1086+
#define SHAPING_FREQ_X 40 // (Hz) The default dominant resonant frequency on the X axis.
1087+
#define SHAPING_ZETA_X 0.15f // Damping ratio of the X axis (range: 0.0 = no damping to 1.0 = critical damping).
10891088
#endif
10901089
#if ENABLED(INPUT_SHAPING_Y)
1091-
#define SHAPING_FREQ_Y 40 // (Hz) The default dominant resonant frequency on the Y axis.
1092-
#define SHAPING_ZETA_Y 0.15f // Damping ratio of the Y axis (range: 0.0 = no damping to 1.0 = critical damping).
1090+
#define SHAPING_FREQ_Y 40 // (Hz) The default dominant resonant frequency on the Y axis.
1091+
#define SHAPING_ZETA_Y 0.15f // Damping ratio of the Y axis (range: 0.0 = no damping to 1.0 = critical damping).
10931092
#endif
1094-
//#define SHAPING_MENU // Add a menu to the LCD to set shaping parameters.
1093+
//#define SHAPING_MIN_FREQ 20 // By default the minimum of the shaping frequencies. Override to affect SRAM usage.
1094+
//#define SHAPING_MAX_STEPRATE 10000 // By default the maximum total step rate of the shaped axes. Override to affect SRAM usage.
1095+
//#define SHAPING_MENU // Add a menu to the LCD to set shaping parameters.
10951096
#endif
10961097

10971098
#define AXIS_RELATIVE_MODES { false, false, false, false }

Marlin/src/inc/SanityCheck.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4272,17 +4272,24 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
42724272

42734273
// Check requirements for Input Shaping
42744274
#if HAS_SHAPING && defined(__AVR__)
4275+
#ifdef SHAPING_MIN_FREQ
4276+
static_assert((SHAPING_MIN_FREQ) > 0, "SHAPING_MIN_FREQ must be > 0.");
4277+
#else
4278+
TERN_(INPUT_SHAPING_X, static_assert((SHAPING_FREQ_X) > 0, "SHAPING_FREQ_X must be > 0 or SHAPING_MIN_FREQ must be set."));
4279+
TERN_(INPUT_SHAPING_Y, static_assert((SHAPING_FREQ_Y) > 0, "SHAPING_FREQ_Y must be > 0 or SHAPING_MIN_FREQ must be set."));
4280+
#endif
42754281
#if ENABLED(INPUT_SHAPING_X)
42764282
#if F_CPU > 16000000
4277-
static_assert((SHAPING_FREQ_X) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_X is below the minimum (20) for AVR 20MHz.");
4283+
static_assert((SHAPING_FREQ_X) == 0 || (SHAPING_FREQ_X) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_X is below the minimum (20) for AVR 20MHz.");
42784284
#else
4279-
static_assert((SHAPING_FREQ_X) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_X is below the minimum (16) for AVR 16MHz.");
4285+
static_assert((SHAPING_FREQ_X) == 0 || (SHAPING_FREQ_X) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_X is below the minimum (16) for AVR 16MHz.");
42804286
#endif
4281-
#elif ENABLED(INPUT_SHAPING_Y)
4287+
#endif
4288+
#if ENABLED(INPUT_SHAPING_Y)
42824289
#if F_CPU > 16000000
4283-
static_assert((SHAPING_FREQ_Y) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_Y is below the minimum (20) for AVR 20MHz.");
4290+
static_assert((SHAPING_FREQ_Y) == 0 || (SHAPING_FREQ_Y) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_Y is below the minimum (20) for AVR 20MHz.");
42844291
#else
4285-
static_assert((SHAPING_FREQ_Y) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_Y is below the minimum (16) for AVR 16MHz.");
4292+
static_assert((SHAPING_FREQ_Y) == 0 || (SHAPING_FREQ_Y) * 2 * 0x10000 >= (STEPPER_TIMER_RATE), "SHAPING_FREQ_Y is below the minimum (16) for AVR 16MHz.");
42864293
#endif
42874294
#endif
42884295
#endif

Marlin/src/module/settings.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,6 @@ typedef struct { bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1,
193193

194194
// Defaults for reset / fill in on load
195195
static const uint32_t _DMA[] PROGMEM = DEFAULT_MAX_ACCELERATION;
196-
static const float _DASU[] PROGMEM = DEFAULT_AXIS_STEPS_PER_UNIT;
197-
static const feedRate_t _DMF[] PROGMEM = DEFAULT_MAX_FEEDRATE;
198196

199197
/**
200198
* Current EEPROM Layout

Marlin/src/module/stepper.h

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -326,49 +326,43 @@ constexpr ena_mask_t enable_overlap[] = {
326326
#endif
327327
};
328328

329+
constexpr float _DASU[] = DEFAULT_AXIS_STEPS_PER_UNIT;
330+
constexpr feedRate_t _DMF[] = DEFAULT_MAX_FEEDRATE;
331+
329332
//static_assert(!any_enable_overlap(), "There is some overlap.");
330333

331334
#if HAS_SHAPING
332335

333-
// These constexpr are used to calculate the shaping queue buffer sizes
334-
constexpr xyze_float_t max_feedrate = DEFAULT_MAX_FEEDRATE;
335-
constexpr xyze_float_t steps_per_unit = DEFAULT_AXIS_STEPS_PER_UNIT;
336-
// MIN_STEP_ISR_FREQUENCY is known at compile time on AVRs and any reduction in SRAM is welcome
337-
#ifdef __AVR__
338-
constexpr float max_isr_rate = _MAX(
339-
LOGICAL_AXIS_LIST(
340-
max_feedrate.e * steps_per_unit.e,
341-
max_feedrate.x * steps_per_unit.x,
342-
max_feedrate.y * steps_per_unit.y,
343-
max_feedrate.z * steps_per_unit.z,
344-
max_feedrate.i * steps_per_unit.i,
345-
max_feedrate.j * steps_per_unit.j,
346-
max_feedrate.k * steps_per_unit.k,
347-
max_feedrate.u * steps_per_unit.u,
348-
max_feedrate.v * steps_per_unit.v,
349-
max_feedrate.w * steps_per_unit.w
350-
)
351-
OPTARG(ADAPTIVE_STEP_SMOOTHING, MIN_STEP_ISR_FREQUENCY)
352-
);
353-
constexpr float max_step_rate = _MIN(max_isr_rate,
354-
TERN0(INPUT_SHAPING_X, max_feedrate.x * steps_per_unit.x) +
355-
TERN0(INPUT_SHAPING_Y, max_feedrate.y * steps_per_unit.y)
356-
);
336+
#ifdef SHAPING_MAX_STEPRATE
337+
constexpr float max_step_rate = SHAPING_MAX_STEPRATE;
357338
#else
358-
constexpr float max_step_rate = TERN0(INPUT_SHAPING_X, max_feedrate.x * steps_per_unit.x) +
359-
TERN0(INPUT_SHAPING_Y, max_feedrate.y * steps_per_unit.y);
339+
constexpr float max_shaped_rate = TERN0(INPUT_SHAPING_X, _DMF[X_AXIS] * _DASU[X_AXIS]) +
340+
TERN0(INPUT_SHAPING_Y, _DMF[Y_AXIS] * _DASU[Y_AXIS]);
341+
#if defined(__AVR__) || !defined(ADAPTIVE_STEP_SMOOTHING)
342+
// MIN_STEP_ISR_FREQUENCY is known at compile time on AVRs and any reduction in SRAM is welcome
343+
template<int INDEX=DISTINCT_AXES> constexpr float max_isr_rate() {
344+
return _MAX(_DMF[INDEX - 1] * _DASU[INDEX - 1], max_isr_rate<INDEX - 1>());
345+
}
346+
template<> constexpr float max_isr_rate<0>() {
347+
return TERN0(ADAPTIVE_STEP_SMOOTHING, MIN_STEP_ISR_FREQUENCY);
348+
}
349+
constexpr float max_step_rate = _MIN(max_isr_rate(), max_shaped_rate);
350+
#else
351+
constexpr float max_step_rate = max_shaped_rate;
352+
#endif
360353
#endif
361-
constexpr uint16_t shaping_echoes = max_step_rate / _MIN(0x7FFFFFFFL OPTARG(INPUT_SHAPING_X, SHAPING_FREQ_X) OPTARG(INPUT_SHAPING_Y, SHAPING_FREQ_Y)) / 2 + 3;
354+
355+
#ifndef SHAPING_MIN_FREQ
356+
#define SHAPING_MIN_FREQ _MIN(0x7FFFFFFFL OPTARG(INPUT_SHAPING_X, SHAPING_FREQ_X) OPTARG(INPUT_SHAPING_Y, SHAPING_FREQ_Y))
357+
#endif
358+
constexpr uint16_t shaping_min_freq = SHAPING_MIN_FREQ,
359+
shaping_echoes = max_step_rate / shaping_min_freq / 2 + 3;
362360

363361
typedef IF<ENABLED(__AVR__), uint16_t, uint32_t>::type shaping_time_t;
364362
enum shaping_echo_t { ECHO_NONE = 0, ECHO_FWD = 1, ECHO_BWD = 2 };
365363
struct shaping_echo_axis_t {
366-
#if ENABLED(INPUT_SHAPING_X)
367-
shaping_echo_t x:2;
368-
#endif
369-
#if ENABLED(INPUT_SHAPING_Y)
370-
shaping_echo_t y:2;
371-
#endif
364+
TERN_(INPUT_SHAPING_X, shaping_echo_t x:2);
365+
TERN_(INPUT_SHAPING_Y, shaping_echo_t y:2);
372366
};
373367

374368
class ShapingQueue {

0 commit comments

Comments
 (0)