0
0
Fork 0
mirror of https://github.com/MarlinFirmware/Marlin.git synced 2025-02-28 03:47:04 +00:00

🎨 Cosmetic stepper updates

Co-Authored-By: tombrazier <68918209+tombrazier@users.noreply.github.com>
This commit is contained in:
Scott Lahteine 2023-03-11 18:51:37 -06:00
parent cb66bff924
commit f9d3939d23
5 changed files with 218 additions and 209 deletions

View file

@ -84,6 +84,13 @@ template <class L, class R> struct IF<true, L, R> { typedef L type; };
#define AXIS_COLLISION(L) (AXIS4_NAME == L || AXIS5_NAME == L || AXIS6_NAME == L || AXIS7_NAME == L || AXIS8_NAME == L || AXIS9_NAME == L) #define AXIS_COLLISION(L) (AXIS4_NAME == L || AXIS5_NAME == L || AXIS6_NAME == L || AXIS7_NAME == L || AXIS8_NAME == L || AXIS9_NAME == L)
// Helpers
#define _RECIP(N) ((N) ? 1.0f / static_cast<float>(N) : 0.0f)
#define _ABS(N) ((N) < 0 ? -(N) : (N))
#define _LS(N) (N = (T)(uint32_t(N) << p))
#define _RS(N) (N = (T)(uint32_t(N) >> p))
#define FI FORCE_INLINE
// Define types based on largest bit width stored value required // Define types based on largest bit width stored value required
#define bits_t(W) typename IF<((W)> 16), uint32_t, typename IF<((W)> 8), uint16_t, uint8_t>::type>::type #define bits_t(W) typename IF<((W)> 16), uint32_t, typename IF<((W)> 8), uint16_t, uint8_t>::type>::type
#define uvalue_t(V) typename IF<((V)>65535), uint32_t, typename IF<((V)>255), uint16_t, uint8_t>::type>::type #define uvalue_t(V) typename IF<((V)>65535), uint32_t, typename IF<((V)>255), uint16_t, uint8_t>::type>::type
@ -101,28 +108,30 @@ struct Flags {
flagbits_t b; flagbits_t b;
typename IF<(N>16), N32, typename IF<(N>8), N16, N8>::type>::type flag; typename IF<(N>16), N32, typename IF<(N>8), N16, N8>::type>::type flag;
}; };
void reset() { b = 0; } FI void reset() { b = 0; }
void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); }
void set(const int n) { b |= (flagbits_t)_BV(n); } FI void set(const int n) { b |= (flagbits_t)_BV(n); }
void clear(const int n) { b &= ~(flagbits_t)_BV(n); } FI void clear(const int n) { b &= ~(flagbits_t)_BV(n); }
bool test(const int n) const { return TEST(b, n); } FI bool test(const int n) const { return TEST(b, n); }
bool operator[](const int n) { return test(n); } FI bool operator[](const int n) { return test(n); }
bool operator[](const int n) const { return test(n); } FI bool operator[](const int n) const { return test(n); }
int size() const { return sizeof(b); } FI int size() const { return sizeof(b); }
FI operator bool() const { return b; }
}; };
// Specialization for a single bool flag // Specialization for a single bool flag
template<> template<>
struct Flags<1> { struct Flags<1> {
bool b; bool b;
void reset() { b = false; } FI void reset() { b = false; }
void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } FI void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); }
void set(const int) { b = true; } FI void set(const int) { b = true; }
void clear(const int) { b = false; } FI void clear(const int) { b = false; }
bool test(const int) const { return b; } FI bool test(const int) const { return b; }
bool& operator[](const int) { return b; } FI bool& operator[](const int) { return b; }
bool operator[](const int) const { return b; } FI bool operator[](const int) const { return b; }
int size() const { return sizeof(b); } FI int size() const { return sizeof(b); }
FI operator bool() const { return b; }
}; };
typedef Flags<8> flags_8_t; typedef Flags<8> flags_8_t;
@ -134,14 +143,15 @@ typedef struct AxisFlags {
struct Flags<LOGICAL_AXES> flags; struct Flags<LOGICAL_AXES> flags;
struct { bool LOGICAL_AXIS_LIST(e:1, x:1, y:1, z:1, i:1, j:1, k:1, u:1, v:1, w:1); }; struct { bool LOGICAL_AXIS_LIST(e:1, x:1, y:1, z:1, i:1, j:1, k:1, u:1, v:1, w:1); };
}; };
void reset() { flags.reset(); } FI void reset() { flags.reset(); }
void set(const int n) { flags.set(n); } FI void set(const int n) { flags.set(n); }
void set(const int n, const bool onoff) { flags.set(n, onoff); } FI void set(const int n, const bool onoff) { flags.set(n, onoff); }
void clear(const int n) { flags.clear(n); } FI void clear(const int n) { flags.clear(n); }
bool test(const int n) const { return flags.test(n); } FI bool test(const int n) const { return flags.test(n); }
bool operator[](const int n) { return flags[n]; } FI bool operator[](const int n) { return flags[n]; }
bool operator[](const int n) const { return flags[n]; } FI bool operator[](const int n) const { return flags[n]; }
int size() const { return sizeof(flags); } FI int size() const { return sizeof(flags); }
FI operator bool() const { return flags; }
} axis_flags_t; } axis_flags_t;
// //
@ -230,13 +240,6 @@ typedef const_float_t const_celsius_float_t;
// Coordinates structures for XY, XYZ, XYZE... // Coordinates structures for XY, XYZ, XYZE...
// //
// Helpers
#define _RECIP(N) ((N) ? 1.0f / static_cast<float>(N) : 0.0f)
#define _ABS(N) ((N) < 0 ? -(N) : (N))
#define _LS(N) (N = (T)(uint32_t(N) << p))
#define _RS(N) (N = (T)(uint32_t(N) >> p))
#define FI FORCE_INLINE
// Forward declarations // Forward declarations
template<typename T> struct XYval; template<typename T> struct XYval;
template<typename T> struct XYZval; template<typename T> struct XYZval;

View file

@ -189,7 +189,7 @@ bool Stepper::abort_current_block;
#endif #endif
uint32_t Stepper::acceleration_time, Stepper::deceleration_time; uint32_t Stepper::acceleration_time, Stepper::deceleration_time;
uint8_t Stepper::steps_per_isr; uint8_t Stepper::steps_per_isr; // Count of steps to perform per Stepper ISR call
#if ENABLED(FREEZE_FEATURE) #if ENABLED(FREEZE_FEATURE)
bool Stepper::frozen; // = false bool Stepper::frozen; // = false
@ -1996,7 +1996,7 @@ void Stepper::pulse_phase_isr() {
void Stepper::shaping_isr() { void Stepper::shaping_isr() {
xy_bool_t step_needed{0}; xy_bool_t step_needed{0};
// Clear the echoes that are ready to process. If the buffers are too full and risk overflo, also apply echoes early. // Clear the echoes that are ready to process. If the buffers are too full and risk overflow, also apply echoes early.
TERN_(INPUT_SHAPING_X, step_needed[X_AXIS] = !ShapingQueue::peek_x() || ShapingQueue::free_count_x() < steps_per_isr); TERN_(INPUT_SHAPING_X, step_needed[X_AXIS] = !ShapingQueue::peek_x() || ShapingQueue::free_count_x() < steps_per_isr);
TERN_(INPUT_SHAPING_Y, step_needed[Y_AXIS] = !ShapingQueue::peek_y() || ShapingQueue::free_count_y() < steps_per_isr); TERN_(INPUT_SHAPING_Y, step_needed[Y_AXIS] = !ShapingQueue::peek_y() || ShapingQueue::free_count_y() < steps_per_isr);
@ -2047,39 +2047,45 @@ void Stepper::pulse_phase_isr() {
// Calculate timer interval, with all limits applied. // Calculate timer interval, with all limits applied.
uint32_t Stepper::calc_timer_interval(uint32_t step_rate) { uint32_t Stepper::calc_timer_interval(uint32_t step_rate) {
#ifdef CPU_32_BIT #ifdef CPU_32_BIT
// In case of high-performance processor, it is able to calculate in real-time
return uint32_t(STEPPER_TIMER_RATE) / step_rate; return uint32_t(STEPPER_TIMER_RATE) / step_rate; // A fast processor can just do integer division
#else #else
// AVR is able to keep up at 30khz Stepping ISR rate. // AVR is able to keep up at 30khz Stepping ISR rate.
constexpr uint32_t min_step_rate = (F_CPU) / 500000U; constexpr uint32_t min_step_rate = (F_CPU) / 500000U; // i.e., 32 or 40
if (step_rate <= min_step_rate) { if (step_rate <= min_step_rate) { // lower step rates
step_rate = 0; step_rate = 0;
uintptr_t table_address = (uintptr_t)&speed_lookuptable_slow[0][0]; return uint16_t(pgm_read_word(uintptr_t(speed_lookuptable_slow)));
return uint16_t(pgm_read_word(table_address));
} }
else { else {
step_rate -= min_step_rate; // Correct for minimal speed step_rate -= min_step_rate; // Correct for minimal speed
if (step_rate >= 0x0800) { // higher step rate if (step_rate >= 0x0800) { // higher step rate
const uint8_t rate_mod_256 = (step_rate & 0x00FF); const uintptr_t table_address = uintptr_t(&speed_lookuptable_fast[uint8_t(step_rate >> 8)]);
const uintptr_t table_address = uintptr_t(&speed_lookuptable_fast[uint8_t(step_rate >> 8)][0]), const uint16_t gain = uint16_t(pgm_read_word(table_address + 2));
gain = uint16_t(pgm_read_word(table_address + 2)); return uint16_t(pgm_read_word(table_address)) - MultiU8X16toH16(uint8_t(step_rate & 0x00FF), gain);
return uint16_t(pgm_read_word(table_address)) - MultiU8X16toH16(rate_mod_256, gain);
} }
else { // lower step rates else { // lower step rates
uintptr_t table_address = uintptr_t(&speed_lookuptable_slow[0][0]); const uintptr_t table_address = uintptr_t(&speed_lookuptable_slow[uint8_t(step_rate >> 3)]);
table_address += (step_rate >> 1) & 0xFFFC;
return uint16_t(pgm_read_word(table_address)) return uint16_t(pgm_read_word(table_address))
- ((uint16_t(pgm_read_word(table_address + 2)) * uint8_t(step_rate & 0x0007)) >> 3); - ((uint16_t(pgm_read_word(table_address + 2)) * uint8_t(step_rate & 0x0007)) >> 3);
} }
} }
#endif
#endif // !CPU_32_BIT
} }
// Get the timer interval and the number of loops to perform per tick // Get the timer interval and the number of loops to perform per tick
uint32_t Stepper::calc_timer_interval(uint32_t step_rate, uint8_t &loops) { uint32_t Stepper::calc_timer_interval(uint32_t step_rate, uint8_t &loops) {
uint8_t multistep = 1; uint8_t multistep = 1;
#if DISABLED(DISABLE_MULTI_STEPPING) #if ENABLED(DISABLE_MULTI_STEPPING)
// Just make sure the step rate is doable
NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X));
#else
// The stepping frequency limits for each multistepping rate // The stepping frequency limits for each multistepping rate
static const uint32_t limit[] PROGMEM = { static const uint32_t limit[] PROGMEM = {
@ -2100,18 +2106,18 @@ uint32_t Stepper::calc_timer_interval(uint32_t step_rate, uint8_t &loops) {
multistep <<= 1; multistep <<= 1;
++idx; ++idx;
}; };
#else
NOMORE(step_rate, uint32_t(MAX_STEP_ISR_FREQUENCY_1X));
#endif #endif
loops = multistep; loops = multistep;
return calc_timer_interval(step_rate); return calc_timer_interval(step_rate);
} }
// This is the last half of the stepper interrupt: This one processes and /**
// properly schedules blocks from the planner. This is executed after creating * This last phase of the stepper interrupt processes and properly
// the step pulses, so it is not time critical, as pulses are already done. * schedules planner blocks. This is executed after the step pulses
* have been done, so it is less time critical.
*/
uint32_t Stepper::block_phase_isr() { uint32_t Stepper::block_phase_isr() {
// If no queued movements, just wait 1ms for the next block // If no queued movements, just wait 1ms for the next block
@ -2555,7 +2561,7 @@ uint32_t Stepper::block_phase_isr() {
if (stepper_extruder != last_moved_extruder) la_advance_steps = 0; if (stepper_extruder != last_moved_extruder) la_advance_steps = 0;
#endif #endif
if (current_block->la_advance_rate) { if (current_block->la_advance_rate) {
// apply LA scaling and discount the effect of frequency scaling // Apply LA scaling and discount the effect of frequency scaling
la_dividend = (advance_dividend.e << current_block->la_scaling) << oversampling_factor; la_dividend = (advance_dividend.e << current_block->la_scaling) << oversampling_factor;
} }
#endif #endif
@ -2597,7 +2603,7 @@ uint32_t Stepper::block_phase_isr() {
if (current_block->steps.z) enable_axis(Z_AXIS); if (current_block->steps.z) enable_axis(Z_AXIS);
#endif #endif
// Mark the time_nominal as not calculated yet // Mark ticks_nominal as not-yet-calculated
ticks_nominal = -1; ticks_nominal = -1;
#if ENABLED(S_CURVE_ACCELERATION) #if ENABLED(S_CURVE_ACCELERATION)
@ -2635,8 +2641,8 @@ uint32_t Stepper::block_phase_isr() {
// the acceleration and speed values calculated in block_phase_isr(). // the acceleration and speed values calculated in block_phase_isr().
// This helps keep LA in sync with, for example, S_CURVE_ACCELERATION. // This helps keep LA in sync with, for example, S_CURVE_ACCELERATION.
la_delta_error += la_dividend; la_delta_error += la_dividend;
const bool step_needed = la_delta_error >= 0; const bool e_step_needed = la_delta_error >= 0;
if (step_needed) { if (e_step_needed) {
count_position.e += count_direction.e; count_position.e += count_direction.e;
la_advance_steps += count_direction.e; la_advance_steps += count_direction.e;
la_delta_error -= advance_divisor; la_delta_error -= advance_divisor;
@ -2647,7 +2653,7 @@ uint32_t Stepper::block_phase_isr() {
TERN_(I2S_STEPPER_STREAM, i2s_push_sample()); TERN_(I2S_STEPPER_STREAM, i2s_push_sample());
if (step_needed) { if (e_step_needed) {
// Enforce a minimum duration for STEP pulse ON // Enforce a minimum duration for STEP pulse ON
#if ISR_PULSE_CONTROL #if ISR_PULSE_CONTROL
USING_TIMED_PULSE(); USING_TIMED_PULSE();

View file

@ -217,10 +217,10 @@
// The loop takes the base time plus the time for all the bresenham logic for R pulses plus the time // The loop takes the base time plus the time for all the bresenham logic for R pulses plus the time
// between pulses for (R-1) pulses. But the user could be enforcing a minimum time so the loop time is: // between pulses for (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) * (R - 1) + _MAX(MIN_ISR_LOOP_CYCLES, MIN_STEPPER_PULSE_CYCLES)) #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))
// Model input shaping as an extra loop call // Model input shaping as an extra loop call
#define ISR_SHAPING_LOOP_CYCLES(R) TERN0(HAS_SHAPING, (R) * ((ISR_LOOP_BASE_CYCLES) + TERN0(INPUT_SHAPING_X, ISR_X_STEPPER_CYCLES) + TERN0(INPUT_SHAPING_Y, ISR_Y_STEPPER_CYCLES))) #define ISR_SHAPING_LOOP_CYCLES(R) (TERN0(HAS_SHAPING, ((ISR_LOOP_BASE_CYCLES) + TERN0(INPUT_SHAPING_X, ISR_X_STEPPER_CYCLES) + TERN0(INPUT_SHAPING_Y, ISR_Y_STEPPER_CYCLES)) << R))
// If linear advance is enabled, then it is handled separately // If linear advance is enabled, then it is handled separately
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
@ -245,17 +245,17 @@
#endif #endif
// Now estimate the total ISR execution time in cycles given a step per ISR multiplier // 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_SHAPING_BASE_CYCLES + ISR_LOOP_CYCLES(R) + ISR_SHAPING_LOOP_CYCLES(R) + ISR_LA_BASE_CYCLES + ISR_LA_LOOP_CYCLES)) / (R)) #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)
// The maximum allowable stepping frequency when doing x128-x1 stepping (in Hz) // 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_128X ((F_CPU) / ISR_EXECUTION_CYCLES(7))
#define MAX_STEP_ISR_FREQUENCY_64X ((F_CPU) / ISR_EXECUTION_CYCLES(64)) #define MAX_STEP_ISR_FREQUENCY_64X ((F_CPU) / ISR_EXECUTION_CYCLES(6))
#define MAX_STEP_ISR_FREQUENCY_32X ((F_CPU) / ISR_EXECUTION_CYCLES(32)) #define MAX_STEP_ISR_FREQUENCY_32X ((F_CPU) / ISR_EXECUTION_CYCLES(5))
#define MAX_STEP_ISR_FREQUENCY_16X ((F_CPU) / ISR_EXECUTION_CYCLES(16)) #define MAX_STEP_ISR_FREQUENCY_16X ((F_CPU) / ISR_EXECUTION_CYCLES(4))
#define MAX_STEP_ISR_FREQUENCY_8X ((F_CPU) / ISR_EXECUTION_CYCLES(8)) #define MAX_STEP_ISR_FREQUENCY_8X ((F_CPU) / ISR_EXECUTION_CYCLES(3))
#define MAX_STEP_ISR_FREQUENCY_4X ((F_CPU) / ISR_EXECUTION_CYCLES(4)) #define MAX_STEP_ISR_FREQUENCY_4X ((F_CPU) / ISR_EXECUTION_CYCLES(2))
#define MAX_STEP_ISR_FREQUENCY_2X ((F_CPU) / ISR_EXECUTION_CYCLES(2)) #define MAX_STEP_ISR_FREQUENCY_2X ((F_CPU) / ISR_EXECUTION_CYCLES(1))
#define MAX_STEP_ISR_FREQUENCY_1X ((F_CPU) / ISR_EXECUTION_CYCLES(1)) #define MAX_STEP_ISR_FREQUENCY_1X ((F_CPU) / ISR_EXECUTION_CYCLES(0))
// The minimum step ISR rate used by ADAPTIVE_STEP_SMOOTHING to target 50% CPU usage // 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. // This does not account for the possibility of multi-stepping.
@ -459,8 +459,6 @@ constexpr ena_mask_t enable_overlap[] = {
// Stepper class definition // Stepper class definition
// //
class Stepper { class Stepper {
friend class KinematicSystem;
friend class DeltaKinematicSystem;
friend void stepperTask(void *); friend void stepperTask(void *);
public: public:
@ -810,8 +808,10 @@ class Stepper {
// Set the current position in steps // Set the current position in steps
static void _set_position(const abce_long_t &spos); static void _set_position(const abce_long_t &spos);
// Calculate timing interval for the given step rate // Calculate the timing interval for the given step rate
static uint32_t calc_timer_interval(uint32_t step_rate); static uint32_t calc_timer_interval(uint32_t step_rate);
// Calculate timing interval and steps-per-ISR for the given step rate
static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t &loops); static uint32_t calc_timer_interval(uint32_t step_rate, uint8_t &loops);
#if ENABLED(S_CURVE_ACCELERATION) #if ENABLED(S_CURVE_ACCELERATION)

View file

@ -24,7 +24,7 @@
#if F_CPU == 16000000 #if F_CPU == 16000000
const uint16_t speed_lookuptable_fast[256][2] PROGMEM = { const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {
{ 62500, 55556}, { 6944, 3268}, { 3676, 1176}, { 2500, 607}, { 1893, 369}, { 1524, 249}, { 1275, 179}, { 1096, 135}, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // dummy first row
{ 961, 105 }, { 856, 85 }, { 771, 69 }, { 702, 58 }, { 644, 49 }, { 595, 42 }, { 553, 37 }, { 516, 32 }, { 961, 105 }, { 856, 85 }, { 771, 69 }, { 702, 58 }, { 644, 49 }, { 595, 42 }, { 553, 37 }, { 516, 32 },
{ 484, 28 }, { 456, 25 }, { 431, 23 }, { 408, 20 }, { 388, 19 }, { 369, 16 }, { 353, 16 }, { 337, 14 }, { 484, 28 }, { 456, 25 }, { 431, 23 }, { 408, 20 }, { 388, 19 }, { 369, 16 }, { 353, 16 }, { 337, 14 },
{ 323, 13 }, { 310, 11 }, { 299, 11 }, { 288, 11 }, { 277, 9 }, { 268, 9 }, { 259, 8 }, { 251, 8 }, { 323, 13 }, { 310, 11 }, { 299, 11 }, { 288, 11 }, { 277, 9 }, { 268, 9 }, { 259, 8 }, { 251, 8 },
@ -96,7 +96,7 @@
#elif F_CPU == 20000000 #elif F_CPU == 20000000
const uint16_t speed_lookuptable_fast[256][2] PROGMEM = { const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {
{62500, 54055}, {8445, 3917}, {4528, 1434}, {3094, 745}, {2349, 456}, {1893, 307}, {1586, 222}, {1364, 167}, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, // dummy first row
{ 1197, 131 }, { 1066, 105 }, { 961, 86 }, { 875, 72 }, { 803, 61 }, { 742, 53 }, { 689, 45 }, { 644, 40 }, { 1197, 131 }, { 1066, 105 }, { 961, 86 }, { 875, 72 }, { 803, 61 }, { 742, 53 }, { 689, 45 }, { 644, 40 },
{ 604, 35 }, { 569, 32 }, { 537, 28 }, { 509, 25 }, { 484, 23 }, { 461, 21 }, { 440, 19 }, { 421, 17 }, { 604, 35 }, { 569, 32 }, { 537, 28 }, { 509, 25 }, { 484, 23 }, { 461, 21 }, { 440, 19 }, { 421, 17 },
{ 404, 16 }, { 388, 15 }, { 373, 14 }, { 359, 13 }, { 346, 12 }, { 334, 11 }, { 323, 10 }, { 313, 10 }, { 404, 16 }, { 388, 15 }, { 373, 14 }, { 359, 13 }, { 346, 12 }, { 334, 11 }, { 323, 10 }, { 313, 10 },