1
0
mirror of https://github.com/MarlinFirmware/Marlin.git synced 2024-11-26 21:36:21 +00:00

Merge pull request #11004 from ejtagle/always_honor_maximum_step_rate

[2.0.x] Fix stepper pulse minimum period and timing calculations
This commit is contained in:
Scott Lahteine 2018-06-12 22:17:22 -05:00 committed by GitHub
commit 81edbfa665
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 282 additions and 266 deletions

View File

@ -108,10 +108,6 @@ extern "C" {
int freeMemory(void);
}
// eeprom
//void eeprom_write_byte(unsigned char *pos, unsigned char value);
//unsigned char eeprom_read_byte(unsigned char *pos);
// timers
#define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz
@ -119,20 +115,15 @@ extern "C" {
#define TEMP_TIMER_NUM 0
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define HAL_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // Cannot be of type double
#define STEPPER_TIMER_PRESCALE 8
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
#define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0)
#define TIMER_OCR_1 OCR1A
#define TIMER_COUNTER_1 TCNT1
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_PRESCALE 8
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // Cannot be of type double
#define TIMER_OCR_0 OCR0A
#define TIMER_COUNTER_0 TCNT0
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
@ -173,6 +164,12 @@ FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t freque
}
}
#define TIMER_OCR_1 OCR1A
#define TIMER_COUNTER_1 TCNT1
#define TIMER_OCR_0 OCR0A
#define TIMER_COUNTER_0 TCNT0
#define _CAT(a, ...) a ## __VA_ARGS__
#define HAL_timer_set_compare(timer, compare) (_CAT(TIMER_OCR_, timer) = compare)
#define HAL_timer_restrain(timer, interval_ticks) NOLESS(_CAT(TIMER_OCR_, timer), _CAT(TIMER_COUNTER_, timer) + interval_ticks)

View File

@ -43,21 +43,22 @@
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
#define STEP_TIMER_NUM 3 // index of timer to use for stepper
#define TEMP_TIMER_NUM 4 // index of timer to use for temperature
#define TONE_TIMER_NUM 6 // index of timer to use for beeper tones
#define HAL_TIMER_RATE ((F_CPU) / 2) // frequency of timers peripherals
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define HAL_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / HAL_TICKS_PER_US)
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
#define STEP_TIMER_NUM 3 // index of timer to use for stepper
#define TEMP_TIMER_NUM 4 // index of timer to use for temperature
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define TONE_TIMER_NUM 6 // index of timer to use for beeper tones
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)

View File

@ -66,22 +66,23 @@
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
#define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals
#define STEP_TIMER_NUM 0 // Timer Index for Stepper
#define TEMP_TIMER_NUM 1 // Timer Index for Temperature
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define PWM_TIMER_NUM 3 // Timer Index for PWM
#define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define HAL_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / HAL_TICKS_PER_US)
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
#define TEMP_TIMER_RATE 1000000
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)

View File

@ -47,37 +47,34 @@
typedef uint16_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFF
#define HAL_TIMER_RATE (F_CPU) // frequency of timers peripherals
#define STEP_TIMER_CHAN 1 // Channel of the timer to use for compare and interrupts
#define TEMP_TIMER_CHAN 1 // Channel of the timer to use for compare and interrupts
#if defined(MCU_STM32F103CB) || defined(MCU_STM32F103C8)
#define STEP_TIMER_NUM 4 // For C8/CB boards, use timer 4
#else
#define STEP_TIMER_NUM 5 // for other boards, five is fine.
#endif
#define STEP_TIMER_CHAN 1 // Channel of the timer to use for compare and interrupts
#define TEMP_TIMER_NUM 2 // index of timer to use for temperature
#define TEMP_TIMER_CHAN 1 // Channel of the timer to use for compare and interrupts
#define PULSE_TIMER_NUM STEP_TIMER_NUM
timer_dev* get_timer_dev(int number);
#define TIMER_DEV(num) get_timer_dev(num)
#define STEP_TIMER_DEV TIMER_DEV(STEP_TIMER_NUM)
#define TEMP_TIMER_DEV TIMER_DEV(TEMP_TIMER_NUM)
//STM32_HAVE_TIMER(n);
#define HAL_TIMER_RATE (F_CPU) // frequency of timers peripherals
#define STEPPER_TIMER_PRESCALE 18 // prescaler for setting stepper timer, 4Mhz
#define STEPPER_TIMER_RATE (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) // frequency of stepper timer
#define HAL_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define TEMP_TIMER_PRESCALE 1000 // prescaler for setting Temp timer, 72Khz
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
#define STEPPER_TIMER_PRESCALE 18 // prescaler for setting stepper timer, 4Mhz
#define STEPPER_TIMER_RATE (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) // frequency of stepper timer
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
timer_dev* get_timer_dev(int number);
#define TIMER_DEV(num) get_timer_dev(num)
#define STEP_TIMER_DEV TIMER_DEV(STEP_TIMER_NUM)
#define TEMP_TIMER_DEV TIMER_DEV(TEMP_TIMER_NUM)
#define ENABLE_STEPPER_DRIVER_INTERRUPT() timer_enable_irq(STEP_TIMER_DEV, STEP_TIMER_CHAN)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() timer_disable_irq(STEP_TIMER_DEV, STEP_TIMER_CHAN)

View File

@ -38,21 +38,22 @@
#define hal_timer_t uint32_t // TODO: One is 16-bit, one 32-bit - does this need to be checked?
#define HAL_TIMER_TYPE_MAX 0xFFFF
#define HAL_TIMER_RATE (HAL_RCC_GetSysClockFreq() / 2) // frequency of timer peripherals
#define STEP_TIMER_NUM 0 // index of timer to use for stepper
#define TEMP_TIMER_NUM 1 // index of timer to use for temperature
#define HAL_TIMER_RATE (HAL_RCC_GetSysClockFreq() / 2) // frequency of timer peripherals
#define STEPPER_TIMER_PRESCALE 54 // was 40,prescaler for setting stepper timer, 2Mhz
#define STEPPER_TIMER_RATE (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) // frequency of stepper timer
#define HAL_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define TEMP_TIMER_PRESCALE 1000 // prescaler for setting Temp timer, 72Khz
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
#define STEPPER_TIMER_PRESCALE 54 // was 40,prescaler for setting stepper timer, 2Mhz
#define STEPPER_TIMER_RATE (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) // frequency of stepper timer
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)

View File

@ -38,21 +38,22 @@
#define hal_timer_t uint32_t // TODO: One is 16-bit, one 32-bit - does this need to be checked?
#define HAL_TIMER_TYPE_MAX 0xFFFF
#define HAL_TIMER_RATE (HAL_RCC_GetSysClockFreq() / 2) // frequency of timer peripherals
#define STEP_TIMER_NUM 0 // index of timer to use for stepper
#define TEMP_TIMER_NUM 1 // index of timer to use for temperature
#define HAL_TIMER_RATE (HAL_RCC_GetSysClockFreq() / 2) // frequency of timer peripherals
#define STEPPER_TIMER_PRESCALE 54 // was 40,prescaler for setting stepper timer, 2Mhz
#define STEPPER_TIMER_RATE (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) // frequency of stepper timer
#define HAL_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define TEMP_TIMER_PRESCALE 1000 // prescaler for setting Temp timer, 72Khz
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
#define TEMP_TIMER_PRESCALE 1000 // prescaler for setting Temp timer, 72Khz
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
#define STEPPER_TIMER_PRESCALE 54 // was 40,prescaler for setting stepper timer, 2Mhz
#define STEPPER_TIMER_RATE (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) // frequency of stepper timer
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)

View File

@ -43,10 +43,6 @@
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
#define STEP_TIMER_NUM 0
#define TEMP_TIMER_NUM 1
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define FTM0_TIMER_PRESCALE 8
#define FTM1_TIMER_PRESCALE 4
#define FTM0_TIMER_PRESCALE_BITS 0b011
@ -56,14 +52,20 @@ typedef uint32_t hal_timer_t;
#define FTM1_TIMER_RATE (F_BUS / FTM1_TIMER_PRESCALE) // 60MHz / 4 = 15MHz
#define HAL_TIMER_RATE (FTM0_TIMER_RATE)
#define STEP_TIMER_NUM 0
#define TEMP_TIMER_NUM 1
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define TEMP_TIMER_FREQUENCY 1000
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define HAL_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000)
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / HAL_TICKS_PER_US)
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000)
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define TEMP_TIMER_FREQUENCY 1000
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)

View File

@ -1444,149 +1444,4 @@
#define USE_EXECUTE_COMMANDS_IMMEDIATE
#endif
// Calculate a default maximum stepper rate, if not supplied
#ifndef MAXIMUM_STEPPER_RATE
#if MINIMUM_STEPPER_PULSE
#define MAXIMUM_STEPPER_RATE (1000000UL / (2UL * (MINIMUM_STEPPER_PULSE)))
#else
#define MAXIMUM_STEPPER_RATE 500000UL
#endif
#endif
//
// Estimate the amount of time the ISR will take to execute
//
#ifdef CPU_32_BIT
// The base ISR takes 792 cycles
#define ISR_BASE_CYCLES 792UL
// 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
// S curve interpolation adds 40 cycles
#if ENABLED(S_CURVE_ACCELERATION)
#define ISR_S_CURVE_CYCLES 40UL
#else
#define ISR_S_CURVE_CYCLES 0UL
#endif
// Stepper Loop base cycles
#define ISR_LOOP_BASE_CYCLES 4UL
// And each stepper takes 16 cycles
#define ISR_STEPPER_CYCLES 16UL
#else
// The base ISR takes 752 cycles
#define ISR_BASE_CYCLES 752UL
// Linear advance base time is 32 cycles
#if ENABLED(LIN_ADVANCE)
#define ISR_LA_BASE_CYCLES 32UL
#else
#define ISR_LA_BASE_CYCLES 0UL
#endif
// 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
// Stepper Loop base cycles
#define ISR_LOOP_BASE_CYCLES 32UL
// And each stepper takes 88 cycles
#define ISR_STEPPER_CYCLES 88UL
#endif
// For each stepper, we add its time
#ifdef HAS_X_STEP
#define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES
#else
#define ISR_X_STEPPER_CYCLES 0UL
#endif
// For each stepper, we add its time
#ifdef HAS_Y_STEP
#define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES
#else
#define ISR_Y_STEPPER_CYCLES 0UL
#endif
// For each stepper, we add its time
#ifdef HAS_Z_STEP
#define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES
#else
#define ISR_Z_STEPPER_CYCLES 0UL
#endif
// E is always interpolated, even for mixing extruders
#define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES
// If linear advance is disabled, then 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
// And the total minimum loop time is, without including the base
#define MIN_ISR_LOOP_CYCLES (ISR_X_STEPPER_CYCLES + ISR_Y_STEPPER_CYCLES + ISR_Z_STEPPER_CYCLES + ISR_E_STEPPER_CYCLES + ISR_MIXING_STEPPER_CYCLES)
// Calculate the minimum MPU cycles needed per pulse to enforce not surpassing the maximum stepper rate
#define _MIN_STEPPER_PULSE_CYCLES(N) MAX((F_CPU) / (MAXIMUM_STEPPER_RATE), ((F_CPU) / 500000UL) * (N))
#if MINIMUM_STEPPER_PULSE
#define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES(MINIMUM_STEPPER_PULSE)
#else
#define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES(1)
#endif
// But the user could be enforcing a minimum time, so the loop time is
#define ISR_LOOP_CYCLES (ISR_LOOP_BASE_CYCLES + MAX(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LOOP_CYCLES))
// If linear advance is enabled, then it is handled separately
#if ENABLED(LIN_ADVANCE)
// Estimate the minimum LA loop time
#if ENABLED(MIXING_EXTRUDER)
#define MIN_ISR_LA_LOOP_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
#else
#define MIN_ISR_LA_LOOP_CYCLES ISR_STEPPER_CYCLES
#endif
// 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
// Now estimate the total ISR execution time in cycles given a step per ISR multiplier
#define ISR_EXECUTION_CYCLES(rate) (((ISR_BASE_CYCLES + ISR_S_CURVE_CYCLES + (ISR_LOOP_CYCLES * rate) + ISR_LA_BASE_CYCLES + ISR_LA_LOOP_CYCLES)) / rate)
// The maximum allowable stepping frequency when doing x128-x1 stepping (in Hz)
#define MAX_128X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(128))
#define MAX_64X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(64))
#define MAX_32X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(32))
#define MAX_16X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(16))
#define MAX_8X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(8))
#define MAX_4X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(4))
#define MAX_2X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(2))
#define MAX_1X_STEP_ISR_FREQUENCY (F_CPU / ISR_EXECUTION_CYCLES(1))
// The minimum allowable frequency for step smoothing will be 1/10 of the maximum nominal frequency (in Hz)
#define MIN_STEP_ISR_FREQUENCY MAX_1X_STEP_ISR_FREQUENCY
// Disable multiple steps per ISR
//#define DISABLE_MULTI_STEPPING
#endif // CONDITIONALS_POST_H

View File

@ -1263,7 +1263,7 @@ void Stepper::isr() {
#else
1
#endif
* (HAL_TICKS_PER_US)
* (STEPPER_TIMER_TICKS_PER_US)
);
/**
@ -1316,10 +1316,10 @@ void Stepper::stepper_pulse_phase_isr() {
// Just update the value we will get at the end of the loop
step_events_completed += events_to_do;
#if MINIMUM_STEPPER_PULSE
// Get the timer count and estimate the end of the pulse
hal_timer_t pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE));
#endif
// Get the timer count and estimate the end of the pulse
hal_timer_t pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t(MIN_PULSE_TICKS);
const hal_timer_t added_step_ticks = ADDED_STEP_TICKS;
// Take multiple steps per interrupt (For high speed moves)
do {
@ -1392,10 +1392,11 @@ void Stepper::stepper_pulse_phase_isr() {
#if MINIMUM_STEPPER_PULSE
// Just wait for the requested pulse duration
while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
// Add to the value, the value needed for the pulse end and ensuring the maximum driver rate is enforced
pulse_end += hal_timer_t(MIN_STEPPER_PULSE_CYCLES) - hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE));
#endif
// Add the delay needed to ensure the maximum driver rate is enforced
if (signed(added_step_ticks) > 0) pulse_end += hal_timer_t(added_step_ticks);
// Pulse stop
#if HAS_X_STEP
PULSE_STOP(X);
@ -1423,15 +1424,15 @@ void Stepper::stepper_pulse_phase_isr() {
// Decrement the count of pending pulses to do
--events_to_do;
#if MINIMUM_STEPPER_PULSE
// For minimum pulse time wait after stopping pulses also
if (events_to_do) {
// Just wait for the requested pulse duration
while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
// For minimum pulse time wait after stopping pulses also
if (events_to_do) {
// Just wait for the requested pulse duration
while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
#if MINIMUM_STEPPER_PULSE
// Add to the value, the time that the pulse must be active (to be used on the next loop)
pulse_end += hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE));
}
#endif
pulse_end += hal_timer_t(MIN_PULSE_TICKS);
#endif
}
} while (events_to_do);
}
@ -1664,7 +1665,7 @@ uint32_t Stepper::stepper_block_phase_isr() {
uint32_t max_rate = current_block->nominal_rate; // Get the maximum rate (maximum event speed)
while (max_rate < MIN_STEP_ISR_FREQUENCY) {
max_rate <<= 1;
if (max_rate >= MAX_1X_STEP_ISR_FREQUENCY) break;
if (max_rate >= MAX_STEP_ISR_FREQUENCY_1X) break;
++oversampling;
}
oversampling_factor = oversampling;
@ -1810,13 +1811,15 @@ uint32_t Stepper::stepper_block_phase_isr() {
REV_E_DIR(active_extruder);
#endif
// Get the timer count and estimate the end of the pulse
hal_timer_t pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t(MIN_PULSE_TICKS);
const hal_timer_t added_step_ticks = ADDED_STEP_TICKS;
// Step E stepper if we have steps
while (LA_steps) {
#if MINIMUM_STEPPER_PULSE
hal_timer_t pulse_end = HAL_timer_get_count(PULSE_TIMER_NUM) + hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE));
#endif
// Set the STEP pulse ON
#if ENABLED(MIXING_EXTRUDER)
MIXING_STEPPERS_LOOP(j) {
// Step mixing steppers (proportionally)
@ -1828,15 +1831,18 @@ uint32_t Stepper::stepper_block_phase_isr() {
E_STEP_WRITE(active_extruder, !INVERT_E_STEP_PIN);
#endif
// Enforce a minimum duration for STEP pulse ON
#if MINIMUM_STEPPER_PULSE
// Just wait for the requested pulse duration
while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
// Add to the value, the value needed for the pulse end and ensuring the maximum driver rate is enforced
pulse_end += hal_timer_t(MIN_STEPPER_PULSE_CYCLES) - hal_timer_t((HAL_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE));
#endif
// Add the delay needed to ensure the maximum driver rate is enforced
if (signed(added_step_ticks) > 0) pulse_end += hal_timer_t(added_step_ticks);
LA_steps < 0 ? ++LA_steps : --LA_steps;
// Set the STEP pulse OFF
#if ENABLED(MIXING_EXTRUDER)
MIXING_STEPPERS_LOOP(j) {
if (delta_error_m[j] >= 0) {
@ -1848,12 +1854,15 @@ uint32_t Stepper::stepper_block_phase_isr() {
E_STEP_WRITE(active_extruder, INVERT_E_STEP_PIN);
#endif
#if MINIMUM_STEPPER_PULSE
// For minimum pulse time wait before looping
// Just wait for the requested pulse duration
if (LA_steps) while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
#endif
// For minimum pulse time wait before looping
// Just wait for the requested pulse duration
if (LA_steps) {
while (HAL_timer_get_count(PULSE_TIMER_NUM) < pulse_end) { /* nada */ }
#if MINIMUM_STEPPER_PULSE
// Add to the value, the time that the pulse must be active (to be used on the next loop)
pulse_end += hal_timer_t(MIN_PULSE_TICKS);
#endif
}
} // LA_steps
return interval;

View File

@ -43,19 +43,169 @@
#ifndef STEPPER_H
#define STEPPER_H
#include "../inc/MarlinConfig.h"
// Disable multiple steps per ISR
//#define DISABLE_MULTI_STEPPING
//
// Estimate the amount of time the Stepper ISR will take to execute
//
#ifndef MINIMUM_STEPPER_PULSE
#define MINIMUM_STEPPER_PULSE 0
#endif
#ifndef MAXIMUM_STEPPER_RATE
#if MINIMUM_STEPPER_PULSE
#define MAXIMUM_STEPPER_RATE (1000000UL / (2UL * (MINIMUM_STEPPER_PULSE)))
#else
#define MAXIMUM_STEPPER_RATE 500000UL
#endif
#endif
#ifdef CPU_32_BIT
// The base ISR takes 792 cycles
#define ISR_BASE_CYCLES 792UL
// 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
// S curve interpolation adds 40 cycles
#if ENABLED(S_CURVE_ACCELERATION)
#define ISR_S_CURVE_CYCLES 40UL
#else
#define ISR_S_CURVE_CYCLES 0UL
#endif
// Stepper Loop base cycles
#define ISR_LOOP_BASE_CYCLES 4UL
// And each stepper takes 16 cycles
#define ISR_STEPPER_CYCLES 16UL
#else
// The base ISR takes 752 cycles
#define ISR_BASE_CYCLES 752UL
// Linear advance base time is 32 cycles
#if ENABLED(LIN_ADVANCE)
#define ISR_LA_BASE_CYCLES 32UL
#else
#define ISR_LA_BASE_CYCLES 0UL
#endif
// 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
// Stepper Loop base cycles
#define ISR_LOOP_BASE_CYCLES 32UL
// And each stepper takes 88 cycles
#define ISR_STEPPER_CYCLES 88UL
#endif
// Add time for each stepper
#ifdef HAS_X_STEP
#define ISR_X_STEPPER_CYCLES ISR_STEPPER_CYCLES
#else
#define ISR_X_STEPPER_CYCLES 0UL
#endif
#ifdef HAS_Y_STEP
#define ISR_Y_STEPPER_CYCLES ISR_STEPPER_CYCLES
#else
#define ISR_Y_STEPPER_CYCLES 0UL
#endif
#ifdef HAS_Z_STEP
#define ISR_Z_STEPPER_CYCLES ISR_STEPPER_CYCLES
#else
#define ISR_Z_STEPPER_CYCLES 0UL
#endif
// E is always interpolated, even for mixing extruders
#define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES
// If linear advance is disabled, then 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
// And the total minimum loop time, not including the base
#define MIN_ISR_LOOP_CYCLES (ISR_X_STEPPER_CYCLES + ISR_Y_STEPPER_CYCLES + ISR_Z_STEPPER_CYCLES + ISR_E_STEPPER_CYCLES + ISR_MIXING_STEPPER_CYCLES)
// Calculate the minimum MPU cycles needed per pulse to enforce, limited to the max stepper rate
#define _MIN_STEPPER_PULSE_CYCLES(N) max((F_CPU) / (MAXIMUM_STEPPER_RATE), ((F_CPU) / 500000UL) * (N))
#if MINIMUM_STEPPER_PULSE
#define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES(MINIMUM_STEPPER_PULSE)
#else
#define MIN_STEPPER_PULSE_CYCLES _MIN_STEPPER_PULSE_CYCLES(1)
#endif
#define MIN_PULSE_TICKS ((PULSE_TIMER_TICKS_PER_US) * (MINIMUM_STEPPER_PULSE))
#define ADDED_STEP_TICKS ((MIN_STEPPER_PULSE_CYCLES) / (PULSE_TIMER_PRESCALE) - MIN_PULSE_TICKS)
// But the user could be enforcing a minimum time, so the loop time is
#define ISR_LOOP_CYCLES (ISR_LOOP_BASE_CYCLES + max(MIN_STEPPER_PULSE_CYCLES, MIN_ISR_LOOP_CYCLES))
// If linear advance is enabled, then it is handled separately
#if ENABLED(LIN_ADVANCE)
// Estimate the minimum LA loop time
#if ENABLED(MIXING_EXTRUDER)
#define MIN_ISR_LA_LOOP_CYCLES ((MIXING_STEPPERS) * (ISR_STEPPER_CYCLES))
#else
#define MIN_ISR_LA_LOOP_CYCLES ISR_STEPPER_CYCLES
#endif
// 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
// Now estimate the total ISR execution time in cycles given a step per ISR multiplier
#define ISR_EXECUTION_CYCLES(R) (((ISR_BASE_CYCLES + ISR_S_CURVE_CYCLES + (ISR_LOOP_CYCLES) * (R) + ISR_LA_BASE_CYCLES + ISR_LA_LOOP_CYCLES)) / (R))
// The maximum allowable stepping frequency when doing x128-x1 stepping (in Hz)
#define MAX_STEP_ISR_FREQUENCY_128X ((F_CPU) / ISR_EXECUTION_CYCLES(128))
#define MAX_STEP_ISR_FREQUENCY_64X ((F_CPU) / ISR_EXECUTION_CYCLES(64))
#define MAX_STEP_ISR_FREQUENCY_32X ((F_CPU) / ISR_EXECUTION_CYCLES(32))
#define MAX_STEP_ISR_FREQUENCY_16X ((F_CPU) / ISR_EXECUTION_CYCLES(16))
#define MAX_STEP_ISR_FREQUENCY_8X ((F_CPU) / ISR_EXECUTION_CYCLES(8))
#define MAX_STEP_ISR_FREQUENCY_4X ((F_CPU) / ISR_EXECUTION_CYCLES(4))
#define MAX_STEP_ISR_FREQUENCY_2X ((F_CPU) / ISR_EXECUTION_CYCLES(2))
#define MAX_STEP_ISR_FREQUENCY_1X ((F_CPU) / ISR_EXECUTION_CYCLES(1))
// The minimum allowable frequency for step smoothing will be 1/10 of the maximum nominal frequency (in Hz)
#define MIN_STEP_ISR_FREQUENCY MAX_STEP_ISR_FREQUENCY_1X
//
// Stepper class definition
//
#include "stepper_indirection.h"
#ifdef __AVR__
#include "speed_lookuptable.h"
#endif
#include "../inc/MarlinConfig.h"
#include "../module/planner.h"
#include "../core/language.h"
class Stepper;
extern Stepper stepper;
class Stepper {
public:
@ -303,14 +453,14 @@ class Stepper {
// The stepping frequency limits for each multistepping rate
static const uint32_t limit[] PROGMEM = {
( MAX_1X_STEP_ISR_FREQUENCY ),
( MAX_2X_STEP_ISR_FREQUENCY >> 1),
( MAX_4X_STEP_ISR_FREQUENCY >> 2),
( MAX_8X_STEP_ISR_FREQUENCY >> 3),
( MAX_16X_STEP_ISR_FREQUENCY >> 4),
( MAX_32X_STEP_ISR_FREQUENCY >> 5),
( MAX_64X_STEP_ISR_FREQUENCY >> 6),
(MAX_128X_STEP_ISR_FREQUENCY >> 7)
( MAX_STEP_ISR_FREQUENCY_1X ),
( MAX_STEP_ISR_FREQUENCY_2X >> 1),
( MAX_STEP_ISR_FREQUENCY_4X >> 2),
( MAX_STEP_ISR_FREQUENCY_8X >> 3),
( MAX_STEP_ISR_FREQUENCY_16X >> 4),
( MAX_STEP_ISR_FREQUENCY_32X >> 5),
( MAX_STEP_ISR_FREQUENCY_64X >> 6),
(MAX_STEP_ISR_FREQUENCY_128X >> 7)
};
// Select the proper multistepping
@ -321,7 +471,7 @@ class Stepper {
++idx;
};
#else
NOMORE(step_rate, uint32_t(MAX_1X_STEP_ISR_FREQUENCY));
NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X));
#endif
*loops = multistep;
@ -367,4 +517,6 @@ class Stepper {
};
extern Stepper stepper;
#endif // STEPPER_H