0
0
Fork 0
mirror of https://github.com/MarlinFirmware/Marlin.git synced 2025-01-22 17:52:57 +00:00

🔧 Minimum Stepper Pulse in Nanoseconds (#27113)

This commit is contained in:
Mihai 2024-06-06 05:26:09 +03:00 committed by GitHub
parent 0169cde8a4
commit 65c19f82b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 113 additions and 174 deletions

View file

@ -2556,27 +2556,28 @@
//#define MINIMUM_STEPPER_PRE_DIR_DELAY 650
/**
* Minimum stepper driver pulse width (in µs)
* 0 : Smallest possible width the MCU can produce, compatible with TMC2xxx drivers
* 0 : Minimum 500ns for LV8729, adjusted in stepper.h
* 1 : Minimum for A4988 and A5984 stepper drivers
* 2 : Minimum for DRV8825 stepper drivers
* 3 : Minimum for TB6600 stepper drivers
* 30 : Minimum for TB6560 stepper drivers
* Minimum stepper driver pulse width (in ns)
* If undefined, these defaults (from Conditionals_adv.h) apply:
* 100 : Minimum for TMC2xxx stepper drivers
* 500 : Minimum for LV8729
* 1000 : Minimum for A4988 and A5984 stepper drivers
* 2000 : Minimum for DRV8825 stepper drivers
* 3000 : Minimum for TB6600 stepper drivers
* 30000 : Minimum for TB6560 stepper drivers
*
* Override the default value based on the driver type set in Configuration.h.
*/
//#define MINIMUM_STEPPER_PULSE 2
//#define MINIMUM_STEPPER_PULSE_NS 2000
/**
* Maximum stepping rate (in Hz) the stepper driver allows
* If undefined, defaults to 1MHz / (2 * MINIMUM_STEPPER_PULSE)
* If undefined, these defaults (from Conditionals_adv.h) apply:
* 5000000 : Maximum for TMC2xxx stepper drivers
* 1000000 : Maximum for LV8729 stepper driver
* 500000 : Maximum for A4988 stepper driver
* 250000 : Maximum for DRV8825 stepper driver
* 150000 : Maximum for TB6600 stepper driver
* 15000 : Maximum for TB6560 stepper driver
* 500000 : Maximum for A4988 stepper driver
* 250000 : Maximum for DRV8825 stepper driver
* 150000 : Maximum for TB6600 stepper driver
* 15000 : Maximum for TB6560 stepper driver
*
* Override the default value based on the driver type set in Configuration.h.
*/

View file

@ -36,13 +36,13 @@
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFE
#define GPT_TIMER_RATE F_BUS_ACTUAL // 150MHz
#define GPT_TIMER_RATE (F_CPU / 4) // 150MHz (Can't use F_BUS_ACTUAL because it's extern volatile)
#define GPT1_TIMER_PRESCALE 2
#define GPT2_TIMER_PRESCALE 10
#define GPT1_TIMER_RATE (GPT_TIMER_RATE / GPT1_TIMER_PRESCALE) // 75MHz
#define GPT2_TIMER_RATE (GPT_TIMER_RATE / GPT2_TIMER_PRESCALE) // 15MHz
#define GPT1_TIMER_RATE (GPT_TIMER_RATE / GPT1_TIMER_PRESCALE) // 150MHz / 2 = 75MHz
#define GPT2_TIMER_RATE (GPT_TIMER_RATE / GPT2_TIMER_PRESCALE) // 150MHz / 10 = 15MHz
#ifndef MF_TIMER_STEP
#define MF_TIMER_STEP 0 // Timer Index for Stepper
@ -57,7 +57,8 @@ typedef uint32_t hal_timer_t;
#define TEMP_TIMER_RATE 1000000
#define TEMP_TIMER_FREQUENCY 1000
#define STEPPER_TIMER_RATE GPT1_TIMER_RATE
#define HAL_TIMER_RATE GPT1_TIMER_RATE
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000)
#define STEPPER_TIMER_PRESCALE ((GPT_TIMER_RATE / 1000000) / STEPPER_TIMER_TICKS_PER_US)

View file

@ -55,9 +55,6 @@
#define CYCLES_PER_MICROSECOND (F_CPU / 1000000UL) // 16 or 20 on AVR
#endif
// Nanoseconds per cycle
#define NANOSECONDS_PER_CYCLE (1000000000.0 / F_CPU)
// Macros to make a string from a macro
#define STRINGIFY_(M) #M
#define STRINGIFY(M) STRINGIFY_(M)

View file

@ -641,6 +641,8 @@
#error "PROBE_PT_[123]_[XY] is now defined using PROBE_PT_[123] with an array { x, y }."
#elif defined(SQUARE_WAVE_STEPPING)
#error "SQUARE_WAVE_STEPPING is now EDGE_STEPPING."
#elif defined(MINIMUM_STEPPER_PULSE)
#error "MINIMUM_STEPPER_PULSE (in µs) is now MINIMUM_STEPPER_PULSE_NS. Multiply old MINIMUM_STEPPER_PULSE x 1000!"
#elif defined(FAN_PIN)
#error "FAN_PIN is now FAN0_PIN."
#elif defined(X_MIN_ENDSTOP_INVERTING) || defined(Y_MIN_ENDSTOP_INVERTING) || defined(Z_MIN_ENDSTOP_INVERTING) \

View file

@ -1198,21 +1198,21 @@
#define MINIMUM_STEPPER_PRE_DIR_DELAY MINIMUM_STEPPER_POST_DIR_DELAY
#endif
#ifndef MINIMUM_STEPPER_PULSE
#ifndef MINIMUM_STEPPER_PULSE_NS
#if HAS_DRIVER(TB6560)
#define MINIMUM_STEPPER_PULSE 30
#define MINIMUM_STEPPER_PULSE_NS 30000
#elif HAS_DRIVER(TB6600)
#define MINIMUM_STEPPER_PULSE 3
#define MINIMUM_STEPPER_PULSE_NS 3000
#elif HAS_DRIVER(DRV8825)
#define MINIMUM_STEPPER_PULSE 2
#define MINIMUM_STEPPER_PULSE_NS 2000
#elif HAS_DRIVER(A4988) || HAS_DRIVER(A5984)
#define MINIMUM_STEPPER_PULSE 1
#elif HAS_TRINAMIC_CONFIG || HAS_TRINAMIC_STANDALONE
#define MINIMUM_STEPPER_PULSE 0
#define MINIMUM_STEPPER_PULSE_NS 1000
#elif HAS_DRIVER(LV8729)
#define MINIMUM_STEPPER_PULSE 0
#define MINIMUM_STEPPER_PULSE_NS 500
#elif HAS_TRINAMIC_CONFIG || HAS_TRINAMIC_STANDALONE
#define MINIMUM_STEPPER_PULSE_NS 100
#else
#define MINIMUM_STEPPER_PULSE 2
// Expecting MAXIMUM_STEPPER_RATE to be defined
#endif
#endif
@ -1230,7 +1230,7 @@
#elif HAS_TRINAMIC_CONFIG || HAS_TRINAMIC_STANDALONE
#define MAXIMUM_STEPPER_RATE 5000000
#else
#define MAXIMUM_STEPPER_RATE 250000
// Expecting MINIMUM_STEPPER_PULSE_NS to be defined
#endif
#endif

View file

@ -519,16 +519,15 @@ xyze_int8_t Stepper::count_direction{0};
#define E_APPLY_DIR(FWD,Q) do{ if (FWD) { FWD_E_DIR(stepper_extruder); } else { REV_E_DIR(stepper_extruder); } }while(0)
#endif
#define CYCLES_TO_NS(CYC) (1000UL * (CYC) / ((F_CPU) / 1000000))
#define NS_PER_PULSE_TIMER_TICK (1000000000UL / (STEPPER_TIMER_RATE))
constexpr uint32_t cycles_to_ns(const uint32_t CYC) { return 1000UL * (CYC) / ((F_CPU) / 1000000); }
constexpr uint32_t ns_per_pulse_timer_tick = 1000000000UL / (STEPPER_TIMER_RATE);
// Round up when converting from ns to timer ticks
#define NS_TO_PULSE_TIMER_TICKS(NS) (((NS) + (NS_PER_PULSE_TIMER_TICK) / 2) / (NS_PER_PULSE_TIMER_TICK))
constexpr hal_timer_t ns_to_pulse_timer_ticks(const uint32_t ns) { return (ns + ns_per_pulse_timer_tick / 2) / ns_per_pulse_timer_tick; }
#define TIMER_SETUP_NS (CYCLES_TO_NS(TIMER_READ_ADD_AND_STORE_CYCLES))
#define PULSE_HIGH_TICK_COUNT hal_timer_t(NS_TO_PULSE_TIMER_TICKS(_MIN_PULSE_HIGH_NS - _MIN(_MIN_PULSE_HIGH_NS, TIMER_SETUP_NS)))
#define PULSE_LOW_TICK_COUNT hal_timer_t(NS_TO_PULSE_TIMER_TICKS(_MIN_PULSE_LOW_NS - _MIN(_MIN_PULSE_LOW_NS, TIMER_SETUP_NS)))
constexpr uint32_t timer_setup_ns = cycles_to_ns(timer_read_add_and_store_cycles);
constexpr hal_timer_t PULSE_HIGH_TICK_COUNT = ns_to_pulse_timer_ticks(_min_pulse_high_ns - _MIN(_min_pulse_high_ns, timer_setup_ns));
constexpr hal_timer_t PULSE_LOW_TICK_COUNT = ns_to_pulse_timer_ticks(_min_pulse_low_ns - _MIN(_min_pulse_low_ns, timer_setup_ns));
#define USING_TIMED_PULSE() hal_timer_t start_pulse_count = 0
#define START_TIMED_PULSE() (start_pulse_count = HAL_timer_get_count(MF_TIMER_PULSE))
@ -1720,7 +1719,7 @@ void Stepper::isr() {
#endif
}
#if MINIMUM_STEPPER_PULSE || MAXIMUM_STEPPER_RATE
#if MINIMUM_STEPPER_PULSE_NS || MAXIMUM_STEPPER_RATE
#define ISR_PULSE_CONTROL 1
#endif
#if ISR_PULSE_CONTROL && DISABLED(I2S_STEPPER_STREAM)
@ -2080,7 +2079,7 @@ void Stepper::pulse_phase_isr() {
TERN_(I2S_STEPPER_STREAM, i2s_push_sample());
// TODO: need to deal with MINIMUM_STEPPER_PULSE over i2s
// TODO: need to deal with MINIMUM_STEPPER_PULSE_NS over i2s
#if ISR_MULTI_STEPS
START_TIMED_PULSE();
AWAIT_HIGH_PULSE();
@ -2256,25 +2255,25 @@ hal_timer_t Stepper::calc_multistep_timer_interval(uint32_t step_rate) {
// The stepping frequency limits for each multistepping rate
static const uint32_t limit[] PROGMEM = {
( MAX_STEP_ISR_FREQUENCY_1X )
, (((F_CPU) / ISR_EXECUTION_CYCLES(1)) >> 1)
max_step_isr_frequency_sh(0)
, max_step_isr_frequency_sh(1)
#if MULTISTEPPING_LIMIT >= 4
, (((F_CPU) / ISR_EXECUTION_CYCLES(2)) >> 2)
, max_step_isr_frequency_sh(2)
#endif
#if MULTISTEPPING_LIMIT >= 8
, (((F_CPU) / ISR_EXECUTION_CYCLES(3)) >> 3)
, max_step_isr_frequency_sh(3)
#endif
#if MULTISTEPPING_LIMIT >= 16
, (((F_CPU) / ISR_EXECUTION_CYCLES(4)) >> 4)
, max_step_isr_frequency_sh(4)
#endif
#if MULTISTEPPING_LIMIT >= 32
, (((F_CPU) / ISR_EXECUTION_CYCLES(5)) >> 5)
, max_step_isr_frequency_sh(5)
#endif
#if MULTISTEPPING_LIMIT >= 64
, (((F_CPU) / ISR_EXECUTION_CYCLES(6)) >> 6)
, max_step_isr_frequency_sh(6)
#endif
#if MULTISTEPPING_LIMIT >= 128
, (((F_CPU) / ISR_EXECUTION_CYCLES(7)) >> 7)
, max_step_isr_frequency_sh(7)
#endif
};
@ -2702,9 +2701,9 @@ hal_timer_t Stepper::block_phase_isr() {
// Decide if axis smoothing is possible
if (stepper.adaptive_step_smoothing_enabled) {
uint32_t max_rate = current_block->nominal_rate; // Get the step event rate
while (max_rate < MIN_STEP_ISR_FREQUENCY) { // As long as more ISRs are possible...
while (max_rate < min_step_isr_frequency) { // As long as more ISRs are possible...
max_rate <<= 1; // Try to double the rate
if (max_rate < MIN_STEP_ISR_FREQUENCY) // Don't exceed the estimated ISR limit
if (max_rate < min_step_isr_frequency) // Don't exceed the estimated ISR limit
++oversampling_factor; // Increase the oversampling (used for left-shift)
}
}
@ -3737,8 +3736,8 @@ void Stepper::report_positions() {
#define _READ_DIR(AXIS) AXIS ##_DIR_READ()
#define _APPLY_DIR(AXIS, FWD) AXIS ##_APPLY_DIR(FWD, true)
#if MINIMUM_STEPPER_PULSE
#define STEP_PULSE_CYCLES ((MINIMUM_STEPPER_PULSE) * CYCLES_PER_MICROSECOND)
#if MINIMUM_STEPPER_PULSE_NS
#define STEP_PULSE_CYCLES ((MINIMUM_STEPPER_PULSE_NS) * CYCLES_PER_MICROSECOND / 1000)
#else
#define STEP_PULSE_CYCLES 0
#endif
@ -3761,7 +3760,7 @@ void Stepper::report_positions() {
#else
#define _SAVE_START() NOOP
#if EXTRA_CYCLES_BABYSTEP > 0
#define _PULSE_WAIT() DELAY_NS(EXTRA_CYCLES_BABYSTEP * NANOSECONDS_PER_CYCLE)
#define _PULSE_WAIT() DELAY_CYCLES(EXTRA_CYCLES_BABYSTEP)
#elif ENABLED(DELTA)
#define _PULSE_WAIT() DELAY_US(2);
#elif STEP_PULSE_CYCLES > 0

View file

@ -146,12 +146,12 @@ constexpr ena_mask_t enable_overlap[] = {
TERN0(INPUT_SHAPING_Y, _ISDMF[Y_AXIS] * _ISDASU[Y_AXIS]) +
TERN0(INPUT_SHAPING_Z, _ISDMF[Z_AXIS] * _ISDASU[Z_AXIS]);
#if defined(__AVR__) || !defined(ADAPTIVE_STEP_SMOOTHING)
// MIN_STEP_ISR_FREQUENCY is known at compile time on AVRs and any reduction in SRAM is welcome
// min_step_isr_frequency is known at compile time on AVRs and any reduction in SRAM is welcome
template<unsigned int INDEX=DISTINCT_AXES> constexpr float max_isr_rate() {
return _MAX(_ISDMF[ISALIM(INDEX - 1, _ISDMF)] * _ISDASU[ISALIM(INDEX - 1, _ISDASU)], max_isr_rate<INDEX - 1>());
}
template<> constexpr float max_isr_rate<0>() {
return TERN0(ADAPTIVE_STEP_SMOOTHING, MIN_STEP_ISR_FREQUENCY);
return TERN0(ADAPTIVE_STEP_SMOOTHING, min_step_isr_frequency);
}
constexpr float max_step_rate = _MIN(max_isr_rate(), max_shaped_rate);
#else

View file

@ -40,184 +40,123 @@
* take longer, pulses will be longer. For example the SKR Pro
* (stm32f407zgt6) requires ~60 cyles.
*/
#define TIMER_READ_ADD_AND_STORE_CYCLES 34UL
constexpr uint32_t timer_read_add_and_store_cycles = 34UL;
// The base ISR
#define ISR_BASE_CYCLES 770UL
constexpr uint32_t isr_base_cycles = 770UL;
// Linear advance base time is 64 cycles
#if ENABLED(LIN_ADVANCE)
#define ISR_LA_BASE_CYCLES 64UL
#else
#define ISR_LA_BASE_CYCLES 0UL
#endif
constexpr uint32_t isr_la_base_cycles = TERN0(LIN_ADVANCE, 64UL);
// S curve interpolation adds 40 cycles
#if ENABLED(S_CURVE_ACCELERATION)
#ifdef STM32G0B1xx
#define ISR_S_CURVE_CYCLES 500UL
#else
#define ISR_S_CURVE_CYCLES 40UL
#endif
#else
#define ISR_S_CURVE_CYCLES 0UL
#endif
constexpr uint32_t isr_s_curve_cycles = TERN0(S_CURVE_ACCELERATION, TERN(STM32G0B1xx, 500UL, 40UL));
// Input shaping base time
#if HAS_ZV_SHAPING
#define ISR_SHAPING_BASE_CYCLES 180UL
#else
#define ISR_SHAPING_BASE_CYCLES 0UL
#endif
constexpr uint32_t isr_shaping_base_cycles = TERN0(HAS_ZV_SHAPING, 180UL);
// Stepper Loop base cycles
#define ISR_LOOP_BASE_CYCLES 4UL
constexpr uint32_t isr_loop_base_cycles = 4UL;
// And each stepper (start + stop pulse) takes in worst case
#define ISR_STEPPER_CYCLES 100UL
constexpr uint32_t isr_stepper_cycles = 100UL;
#else
// Cycles to perform actions in START_TIMED_PULSE
#define TIMER_READ_ADD_AND_STORE_CYCLES 13UL
constexpr uint32_t timer_read_add_and_store_cycles = 13UL;
// The base ISR
#define ISR_BASE_CYCLES 882UL
constexpr uint32_t isr_base_cycles = 882UL;
// Linear advance base time is 32 cycles
#if ENABLED(LIN_ADVANCE)
#define ISR_LA_BASE_CYCLES 30UL
#else
#define ISR_LA_BASE_CYCLES 0UL
#endif
constexpr uint32_t isr_la_base_cycles = TERN0(LIN_ADVANCE, 30UL);
// S curve interpolation adds 160 cycles
#if ENABLED(S_CURVE_ACCELERATION)
#define ISR_S_CURVE_CYCLES 160UL
#else
#define ISR_S_CURVE_CYCLES 0UL
#endif
constexpr uint32_t isr_s_curve_cycles = TERN0(S_CURVE_ACCELERATION, 160UL);
// Input shaping base time
#if HAS_ZV_SHAPING
#define ISR_SHAPING_BASE_CYCLES 290UL
#else
#define ISR_SHAPING_BASE_CYCLES 0UL
#endif
constexpr uint32_t isr_shaping_base_cycles = TERN0(HAS_ZV_SHAPING, 290UL);
// Stepper Loop base cycles
#define ISR_LOOP_BASE_CYCLES 32UL
constexpr uint32_t isr_loop_base_cycles = 32UL;
// And each stepper (start + stop pulse) takes in worst case
#define ISR_STEPPER_CYCLES 60UL
constexpr uint32_t isr_stepper_cycles = 60UL;
#endif
// If linear advance is disabled, the loop also handles them
#if DISABLED(LIN_ADVANCE) && ENABLED(MIXING_EXTRUDER)
#define ISR_MIXING_STEPPER_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
#else
#define ISR_MIXING_STEPPER_CYCLES 0UL
#endif
constexpr uint32_t isr_mixing_stepper_cycles = (0UL
#if DISABLED(LIN_ADVANCE) && ENABLED(MIXING_EXTRUDER)
+ (MIXING_STEPPERS) * isr_stepper_cycles
#endif
);
// Add time for each stepper
#if HAS_X_STEP
#define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_Y_STEP
#define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_Z_STEP
#define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_I_STEP
#define ISR_I_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_J_STEP
#define ISR_J_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_K_STEP
#define ISR_K_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_U_STEP
#define ISR_U_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_V_STEP
#define ISR_V_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_W_STEP
#define ISR_W_STEPPER_CYCLES ISR_STEPPER_CYCLES
#endif
#if HAS_EXTRUDERS
#define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES // E is always interpolated, even for mixing extruders
#endif
// And the total minimum loop time, not including the base
#define _PLUS_AXIS_CYCLES(A) + (ISR_##A##_STEPPER_CYCLES)
#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_MAP(_PLUS_AXIS_CYCLES))
// Calculate the minimum MPU cycles needed per pulse to enforce, limited to the max stepper rate
#define _MIN_STEPPER_PULSE_CYCLES(N) _MAX(uint32_t((F_CPU) / (MAXIMUM_STEPPER_RATE)), ((F_CPU) / 500000UL) * (N))
#if MINIMUM_STEPPER_PULSE
#define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES(uint32_t(MINIMUM_STEPPER_PULSE))
#elif HAS_DRIVER(LV8729)
#define MIN_STEPPER_PULSE_CYCLES uint32_t((((F_CPU) - 1) / 2000000) + 1) // 0.5µs, aka 500ns
#else
#define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES(1UL)
#endif
// And the total minimum loop time, for all steppers, not including the base
constexpr uint32_t min_isr_loop_cycles = isr_mixing_stepper_cycles + LOGICAL_AXES * isr_stepper_cycles;
// Calculate the minimum pulse times (high and low)
#if MINIMUM_STEPPER_PULSE && MAXIMUM_STEPPER_RATE
constexpr uint32_t _MIN_STEP_PERIOD_NS = 1000000000UL / MAXIMUM_STEPPER_RATE;
constexpr uint32_t _MIN_PULSE_HIGH_NS = 1000UL * MINIMUM_STEPPER_PULSE;
constexpr uint32_t _MIN_PULSE_LOW_NS = _MAX((_MIN_STEP_PERIOD_NS - _MIN(_MIN_STEP_PERIOD_NS, _MIN_PULSE_HIGH_NS)), _MIN_PULSE_HIGH_NS);
#elif MINIMUM_STEPPER_PULSE
// Assume 50% duty cycle
constexpr uint32_t _MIN_PULSE_HIGH_NS = 1000UL * MINIMUM_STEPPER_PULSE;
constexpr uint32_t _MIN_PULSE_LOW_NS = _MIN_PULSE_HIGH_NS;
#elif MAXIMUM_STEPPER_RATE
// Assume 50% duty cycle
constexpr uint32_t _MIN_PULSE_HIGH_NS = 500000000UL / MAXIMUM_STEPPER_RATE;
constexpr uint32_t _MIN_PULSE_LOW_NS = _MIN_PULSE_HIGH_NS;
#if defined(MINIMUM_STEPPER_PULSE_NS) && defined(MAXIMUM_STEPPER_RATE)
constexpr uint32_t _min_step_period_ns = 1000000000UL / (MAXIMUM_STEPPER_RATE),
_min_pulse_high_ns = MINIMUM_STEPPER_PULSE_NS,
_min_pulse_low_ns = _MAX(_min_step_period_ns - _MIN(_min_step_period_ns, _min_pulse_high_ns), _min_pulse_high_ns);
#elif defined(MINIMUM_STEPPER_PULSE_NS)
// Assume equal high and low pulse durations
constexpr uint32_t _min_pulse_high_ns = MINIMUM_STEPPER_PULSE_NS,
_min_pulse_low_ns = _min_pulse_high_ns;
#elif defined(MAXIMUM_STEPPER_RATE)
// Assume equal high and low pulse durations
constexpr uint32_t _min_pulse_high_ns = 500000000UL / MAXIMUM_STEPPER_RATE,
_min_pulse_low_ns = _min_pulse_high_ns;
#else
#error "Expected at least one of MINIMUM_STEPPER_PULSE or MAXIMUM_STEPPER_RATE to be defined"
#error "At least one of MINIMUM_STEPPER_PULSE_NS or MAXIMUM_STEPPER_RATE must be defined"
#endif
// Calculate the minimum MPU cycles needed per pulse to enforce
constexpr uint32_t min_stepper_pulse_cycles = _min_pulse_high_ns * CYCLES_PER_MICROSECOND / 1000;
// The loop takes the base time plus the time for all the bresenham logic for 1 << R pulses plus the time
// between pulses for ((1 << R) - 1) pulses. But the user could be enforcing a minimum time so the loop time is:
#define ISR_LOOP_CYCLES(R) ((ISR_LOOP_BASE_CYCLES + MIN_ISR_LOOP_CYCLES + MIN_STEPPER_PULSE_CYCLES) * ((1UL << R) - 1) + _MAX(MIN_ISR_LOOP_CYCLES, MIN_STEPPER_PULSE_CYCLES))
constexpr uint32_t isr_loop_cycles(const int R) { return ((isr_loop_base_cycles + min_isr_loop_cycles + min_stepper_pulse_cycles) * ((1UL << R) - 1) + _MAX(min_isr_loop_cycles, min_stepper_pulse_cycles)); }
// Model input shaping as an extra loop call
#define ISR_SHAPING_LOOP_CYCLES(R) (TERN0(HAS_ZV_SHAPING, (ISR_LOOP_BASE_CYCLES + TERN0(INPUT_SHAPING_X, ISR_X_STEPPER_CYCLES) + TERN0(INPUT_SHAPING_Y, ISR_Y_STEPPER_CYCLES) + TERN0(INPUT_SHAPING_Z, ISR_Z_STEPPER_CYCLES)) << R))
constexpr uint32_t isr_shaping_loop_cycles(const int R) {
return (
#if HAS_ZV_SHAPING
isr_loop_base_cycles
+ isr_stepper_cycles * COUNT_ENABLED(INPUT_SHAPING_X, INPUT_SHAPING_Y, INPUT_SHAPING_Z)
#else
0
#endif
) << R;
}
// If linear advance is enabled, then it is handled separately
#if ENABLED(LIN_ADVANCE)
// Estimate the minimum LA loop time
#if ENABLED(MIXING_EXTRUDER) // ToDo: ???
constexpr uint32_t min_isr_la_loop_cycles = (isr_stepper_cycles
// ToDo: ???
// HELP ME: What is what?
// Directions are set up for MIXING_STEPPERS - like before.
// Finding the right stepper may last up to MIXING_STEPPERS loops in get_next_stepper().
// These loops are a bit faster than advancing a bresenham counter.
// Always only one E stepper is stepped.
#define MIN_ISR_LA_LOOP_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
#else
#define MIN_ISR_LA_LOOP_CYCLES ISR_STEPPER_CYCLES
#endif
* TERN1(MIXING_EXTRUDER, (MIXING_STEPPERS))
);
// And the real loop time
#define ISR_LA_LOOP_CYCLES _MAX(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LA_LOOP_CYCLES)
#else
#define ISR_LA_LOOP_CYCLES 0UL
#endif
// The real LA loop time will be the larger minimum (pulse or loop)
constexpr uint32_t isr_la_loop_cycles = TERN0(LIN_ADVANCE, _MAX(min_stepper_pulse_cycles, min_isr_la_loop_cycles));
// Estimate the total ISR execution time in cycles given a step-per-ISR shift multiplier
#define ISR_EXECUTION_CYCLES(R) ((ISR_BASE_CYCLES + ISR_S_CURVE_CYCLES + ISR_SHAPING_BASE_CYCLES + ISR_LOOP_CYCLES(R) + ISR_SHAPING_LOOP_CYCLES(R) + ISR_LA_BASE_CYCLES + ISR_LA_LOOP_CYCLES) >> R)
constexpr uint32_t isr_execution_cycles(const int R) { return (isr_base_cycles + isr_s_curve_cycles + isr_shaping_base_cycles + isr_loop_cycles(R) + isr_shaping_loop_cycles(R) + isr_la_base_cycles + isr_la_loop_cycles) >> R; }
// The maximum allowable stepping frequency when doing 1x stepping (in Hz)
#define MAX_STEP_ISR_FREQUENCY_1X ((F_CPU) / ISR_EXECUTION_CYCLES(0))
constexpr uint32_t max_step_isr_frequency_1x = (F_CPU) / isr_execution_cycles(0);
constexpr uint32_t max_step_isr_frequency_sh(const int S) { return ((F_CPU) / isr_execution_cycles(S)) >> S; }
// The minimum step ISR rate used by ADAPTIVE_STEP_SMOOTHING to target 50% CPU usage
// This does not account for the possibility of multi-stepping.
#define MIN_STEP_ISR_FREQUENCY (MAX_STEP_ISR_FREQUENCY_1X >> 1)
constexpr uint32_t min_step_isr_frequency = max_step_isr_frequency_1x >> 1;