|
@@ -199,7 +199,7 @@ IF_DISABLED(ADAPTIVE_STEP_SMOOTHING, constexpr) uint8_t Stepper::oversampling_fa
|
199
|
199
|
|
200
|
200
|
xyze_long_t Stepper::delta_error{0};
|
201
|
201
|
|
202
|
|
-xyze_ulong_t Stepper::advance_dividend{0};
|
|
202
|
+xyze_long_t Stepper::advance_dividend{0};
|
203
|
203
|
uint32_t Stepper::advance_divisor = 0,
|
204
|
204
|
Stepper::step_events_completed = 0, // The number of step events executed in the current block
|
205
|
205
|
Stepper::accelerate_until, // The count at which to stop accelerating
|
|
@@ -232,6 +232,20 @@ uint32_t Stepper::advance_divisor = 0,
|
232
|
232
|
Stepper::la_advance_steps = 0;
|
233
|
233
|
#endif
|
234
|
234
|
|
|
235
|
+#if ENABLED(INPUT_SHAPING)
|
|
236
|
+ shaping_time_t DelayTimeManager::now = 0;
|
|
237
|
+ ParamDelayQueue Stepper::shaping_dividend_queue;
|
|
238
|
+ DelayQueue<shaping_dividends> Stepper::shaping_queue;
|
|
239
|
+ #if HAS_SHAPING_X
|
|
240
|
+ shaping_time_t DelayTimeManager::delay_x;
|
|
241
|
+ ShapeParams Stepper::shaping_x;
|
|
242
|
+ #endif
|
|
243
|
+ #if HAS_SHAPING_Y
|
|
244
|
+ shaping_time_t DelayTimeManager::delay_y;
|
|
245
|
+ ShapeParams Stepper::shaping_y;
|
|
246
|
+ #endif
|
|
247
|
+#endif
|
|
248
|
+
|
235
|
249
|
#if ENABLED(INTEGRATED_BABYSTEPPING)
|
236
|
250
|
uint32_t Stepper::nextBabystepISR = BABYSTEP_NEVER;
|
237
|
251
|
#endif
|
|
@@ -458,12 +472,10 @@ xyze_int8_t Stepper::count_direction{0};
|
458
|
472
|
#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)))
|
459
|
473
|
|
460
|
474
|
#define USING_TIMED_PULSE() hal_timer_t start_pulse_count = 0
|
461
|
|
-#define START_TIMED_PULSE(DIR) (start_pulse_count = HAL_timer_get_count(MF_TIMER_PULSE))
|
462
|
|
-#define AWAIT_TIMED_PULSE(DIR) while (PULSE_##DIR##_TICK_COUNT > HAL_timer_get_count(MF_TIMER_PULSE) - start_pulse_count) { }
|
463
|
|
-#define START_HIGH_PULSE() START_TIMED_PULSE(HIGH)
|
464
|
|
-#define AWAIT_HIGH_PULSE() AWAIT_TIMED_PULSE(HIGH)
|
465
|
|
-#define START_LOW_PULSE() START_TIMED_PULSE(LOW)
|
466
|
|
-#define AWAIT_LOW_PULSE() AWAIT_TIMED_PULSE(LOW)
|
|
475
|
+#define START_TIMED_PULSE() (start_pulse_count = HAL_timer_get_count(MF_TIMER_PULSE))
|
|
476
|
+#define AWAIT_TIMED_PULSE(DIR) while (PULSE_##DIR##_TICK_COUNT > HAL_timer_get_count(MF_TIMER_PULSE) - start_pulse_count) { /* nada */ }
|
|
477
|
+#define AWAIT_HIGH_PULSE() AWAIT_TIMED_PULSE(HIGH)
|
|
478
|
+#define AWAIT_LOW_PULSE() AWAIT_TIMED_PULSE(LOW)
|
467
|
479
|
|
468
|
480
|
#if MINIMUM_STEPPER_PRE_DIR_DELAY > 0
|
469
|
481
|
#define DIR_WAIT_BEFORE() DELAY_NS(MINIMUM_STEPPER_PRE_DIR_DELAY)
|
|
@@ -559,6 +571,16 @@ void Stepper::disable_all_steppers() {
|
559
|
571
|
TERN_(EXTENSIBLE_UI, ExtUI::onSteppersDisabled());
|
560
|
572
|
}
|
561
|
573
|
|
|
574
|
+#define SET_STEP_DIR(A) \
|
|
575
|
+ if (motor_direction(_AXIS(A))) { \
|
|
576
|
+ A##_APPLY_DIR(INVERT_##A##_DIR, false); \
|
|
577
|
+ count_direction[_AXIS(A)] = -1; \
|
|
578
|
+ } \
|
|
579
|
+ else { \
|
|
580
|
+ A##_APPLY_DIR(!INVERT_##A##_DIR, false); \
|
|
581
|
+ count_direction[_AXIS(A)] = 1; \
|
|
582
|
+ }
|
|
583
|
+
|
562
|
584
|
/**
|
563
|
585
|
* Set the stepper direction of each axis
|
564
|
586
|
*
|
|
@@ -570,16 +592,6 @@ void Stepper::set_directions() {
|
570
|
592
|
|
571
|
593
|
DIR_WAIT_BEFORE();
|
572
|
594
|
|
573
|
|
- #define SET_STEP_DIR(A) \
|
574
|
|
- if (motor_direction(_AXIS(A))) { \
|
575
|
|
- A##_APPLY_DIR(INVERT_##A##_DIR, false); \
|
576
|
|
- count_direction[_AXIS(A)] = -1; \
|
577
|
|
- } \
|
578
|
|
- else { \
|
579
|
|
- A##_APPLY_DIR(!INVERT_##A##_DIR, false); \
|
580
|
|
- count_direction[_AXIS(A)] = 1; \
|
581
|
|
- }
|
582
|
|
-
|
583
|
595
|
TERN_(HAS_X_DIR, SET_STEP_DIR(X)); // A
|
584
|
596
|
TERN_(HAS_Y_DIR, SET_STEP_DIR(Y)); // B
|
585
|
597
|
TERN_(HAS_Z_DIR, SET_STEP_DIR(Z)); // C
|
|
@@ -1467,8 +1479,20 @@ void Stepper::isr() {
|
1467
|
1479
|
// Enable ISRs to reduce USART processing latency
|
1468
|
1480
|
hal.isr_on();
|
1469
|
1481
|
|
|
1482
|
+ #if ENABLED(INPUT_SHAPING)
|
|
1483
|
+ // Speed limiting should ensure the buffers never get full. But if somehow they do, stutter rather than overflow.
|
|
1484
|
+ if (!nextMainISR) {
|
|
1485
|
+ TERN_(HAS_SHAPING_X, if (shaping_dividend_queue.free_count_x() == 0) nextMainISR = shaping_dividend_queue.peek_x() + 1);
|
|
1486
|
+ TERN_(HAS_SHAPING_Y, if (shaping_dividend_queue.free_count_y() == 0) NOLESS(nextMainISR, shaping_dividend_queue.peek_y() + 1));
|
|
1487
|
+ TERN_(HAS_SHAPING_X, if (shaping_queue.free_count_x() < steps_per_isr) NOLESS(nextMainISR, shaping_queue.peek_x() + 1));
|
|
1488
|
+ TERN_(HAS_SHAPING_Y, if (shaping_queue.free_count_y() < steps_per_isr) NOLESS(nextMainISR, shaping_queue.peek_y() + 1));
|
|
1489
|
+ }
|
|
1490
|
+ #endif
|
|
1491
|
+
|
1470
|
1492
|
if (!nextMainISR) pulse_phase_isr(); // 0 = Do coordinated axes Stepper pulses
|
1471
|
1493
|
|
|
1494
|
+ TERN_(INPUT_SHAPING, shaping_isr()); // Do Shaper stepping, if needed
|
|
1495
|
+
|
1472
|
1496
|
#if ENABLED(LIN_ADVANCE)
|
1473
|
1497
|
if (!nextAdvanceISR) { // 0 = Do Linear Advance E Stepper pulses
|
1474
|
1498
|
advance_isr();
|
|
@@ -1497,10 +1521,14 @@ void Stepper::isr() {
|
1497
|
1521
|
|
1498
|
1522
|
// Get the interval to the next ISR call
|
1499
|
1523
|
const uint32_t interval = _MIN(
|
1500
|
|
- uint32_t(HAL_TIMER_TYPE_MAX), // Come back in a very long time
|
1501
|
|
- nextMainISR // Time until the next Pulse / Block phase
|
1502
|
|
- OPTARG(LIN_ADVANCE, nextAdvanceISR) // Come back early for Linear Advance?
|
1503
|
|
- OPTARG(INTEGRATED_BABYSTEPPING, nextBabystepISR) // Come back early for Babystepping?
|
|
1524
|
+ uint32_t(HAL_TIMER_TYPE_MAX), // Come back in a very long time
|
|
1525
|
+ nextMainISR // Time until the next Pulse / Block phase
|
|
1526
|
+ OPTARG(HAS_SHAPING_X, shaping_dividend_queue.peek_x()) // Time until next input shaping dividend change for X
|
|
1527
|
+ OPTARG(HAS_SHAPING_Y, shaping_dividend_queue.peek_y()) // Time until next input shaping dividend change for Y
|
|
1528
|
+ OPTARG(HAS_SHAPING_X, shaping_queue.peek_x()) // Time until next input shaping echo for X
|
|
1529
|
+ OPTARG(HAS_SHAPING_Y, shaping_queue.peek_y()) // Time until next input shaping echo for Y
|
|
1530
|
+ OPTARG(LIN_ADVANCE, nextAdvanceISR) // Come back early for Linear Advance?
|
|
1531
|
+ OPTARG(INTEGRATED_BABYSTEPPING, nextBabystepISR) // Come back early for Babystepping?
|
1504
|
1532
|
);
|
1505
|
1533
|
|
1506
|
1534
|
//
|
|
@@ -1512,6 +1540,8 @@ void Stepper::isr() {
|
1512
|
1540
|
|
1513
|
1541
|
nextMainISR -= interval;
|
1514
|
1542
|
|
|
1543
|
+ TERN_(INPUT_SHAPING, DelayTimeManager::decrement_delays(interval));
|
|
1544
|
+
|
1515
|
1545
|
#if ENABLED(LIN_ADVANCE)
|
1516
|
1546
|
if (nextAdvanceISR != LA_ADV_NEVER) nextAdvanceISR -= interval;
|
1517
|
1547
|
#endif
|
|
@@ -1604,11 +1634,19 @@ void Stepper::pulse_phase_isr() {
|
1604
|
1634
|
// If we must abort the current block, do so!
|
1605
|
1635
|
if (abort_current_block) {
|
1606
|
1636
|
abort_current_block = false;
|
1607
|
|
- if (current_block) discard_current_block();
|
|
1637
|
+ if (current_block) {
|
|
1638
|
+ discard_current_block();
|
|
1639
|
+ #if ENABLED(INPUT_SHAPING)
|
|
1640
|
+ shaping_dividend_queue.purge();
|
|
1641
|
+ shaping_queue.purge();
|
|
1642
|
+ TERN_(HAS_SHAPING_X, delta_error.x = 0);
|
|
1643
|
+ TERN_(HAS_SHAPING_Y, delta_error.y = 0);
|
|
1644
|
+ #endif
|
|
1645
|
+ }
|
1608
|
1646
|
}
|
1609
|
1647
|
|
1610
|
1648
|
// If there is no current block, do nothing
|
1611
|
|
- if (!current_block) return;
|
|
1649
|
+ if (!current_block || step_events_completed >= step_event_count) return;
|
1612
|
1650
|
|
1613
|
1651
|
// Skipping step processing causes motion to freeze
|
1614
|
1652
|
if (TERN0(FREEZE_FEATURE, frozen)) return;
|
|
@@ -1627,6 +1665,9 @@ void Stepper::pulse_phase_isr() {
|
1627
|
1665
|
#endif
|
1628
|
1666
|
xyze_bool_t step_needed{0};
|
1629
|
1667
|
|
|
1668
|
+ // Direct Stepping page?
|
|
1669
|
+ const bool is_page = current_block->is_page();
|
|
1670
|
+
|
1630
|
1671
|
do {
|
1631
|
1672
|
#define _APPLY_STEP(AXIS, INV, ALWAYS) AXIS ##_APPLY_STEP(INV, ALWAYS)
|
1632
|
1673
|
#define _INVERT_STEP_PIN(AXIS) INVERT_## AXIS ##_STEP_PIN
|
|
@@ -1641,6 +1682,22 @@ void Stepper::pulse_phase_isr() {
|
1641
|
1682
|
} \
|
1642
|
1683
|
}while(0)
|
1643
|
1684
|
|
|
1685
|
+ #define PULSE_PREP_SHAPING(AXIS, DIVIDEND) do{ \
|
|
1686
|
+ delta_error[_AXIS(AXIS)] += (DIVIDEND); \
|
|
1687
|
+ if ((MAXDIR(AXIS) && delta_error[_AXIS(AXIS)] <= -0x30000000L) || (MINDIR(AXIS) && delta_error[_AXIS(AXIS)] >= 0x30000000L)) { \
|
|
1688
|
+ TBI(last_direction_bits, _AXIS(AXIS)); \
|
|
1689
|
+ DIR_WAIT_BEFORE(); \
|
|
1690
|
+ SET_STEP_DIR(AXIS); \
|
|
1691
|
+ DIR_WAIT_AFTER(); \
|
|
1692
|
+ } \
|
|
1693
|
+ step_needed[_AXIS(AXIS)] = (MAXDIR(AXIS) && delta_error[_AXIS(AXIS)] >= 0x10000000L) || \
|
|
1694
|
+ (MINDIR(AXIS) && delta_error[_AXIS(AXIS)] <= -0x10000000L); \
|
|
1695
|
+ if (step_needed[_AXIS(AXIS)]) { \
|
|
1696
|
+ count_position[_AXIS(AXIS)] += count_direction[_AXIS(AXIS)]; \
|
|
1697
|
+ delta_error[_AXIS(AXIS)] += MAXDIR(AXIS) ? -0x20000000L : 0x20000000L; \
|
|
1698
|
+ } \
|
|
1699
|
+ }while(0)
|
|
1700
|
+
|
1644
|
1701
|
// Start an active pulse if needed
|
1645
|
1702
|
#define PULSE_START(AXIS) do{ \
|
1646
|
1703
|
if (step_needed[_AXIS(AXIS)]) { \
|
|
@@ -1655,9 +1712,6 @@ void Stepper::pulse_phase_isr() {
|
1655
|
1712
|
} \
|
1656
|
1713
|
}while(0)
|
1657
|
1714
|
|
1658
|
|
- // Direct Stepping page?
|
1659
|
|
- const bool is_page = current_block->is_page();
|
1660
|
|
-
|
1661
|
1715
|
#if ENABLED(DIRECT_STEPPING)
|
1662
|
1716
|
// Direct stepping is currently not ready for HAS_I_AXIS
|
1663
|
1717
|
if (is_page) {
|
|
@@ -1765,12 +1819,22 @@ void Stepper::pulse_phase_isr() {
|
1765
|
1819
|
#endif // DIRECT_STEPPING
|
1766
|
1820
|
|
1767
|
1821
|
if (!is_page) {
|
|
1822
|
+ TERN_(INPUT_SHAPING, shaping_queue.enqueue());
|
|
1823
|
+
|
1768
|
1824
|
// Determine if pulses are needed
|
1769
|
1825
|
#if HAS_X_STEP
|
1770
|
|
- PULSE_PREP(X);
|
|
1826
|
+ #if HAS_SHAPING_X
|
|
1827
|
+ PULSE_PREP_SHAPING(X, advance_dividend.x);
|
|
1828
|
+ #else
|
|
1829
|
+ PULSE_PREP(X);
|
|
1830
|
+ #endif
|
1771
|
1831
|
#endif
|
1772
|
1832
|
#if HAS_Y_STEP
|
1773
|
|
- PULSE_PREP(Y);
|
|
1833
|
+ #if HAS_SHAPING_Y
|
|
1834
|
+ PULSE_PREP_SHAPING(Y, advance_dividend.y);
|
|
1835
|
+ #else
|
|
1836
|
+ PULSE_PREP(Y);
|
|
1837
|
+ #endif
|
1774
|
1838
|
#endif
|
1775
|
1839
|
#if HAS_Z_STEP
|
1776
|
1840
|
PULSE_PREP(Z);
|
|
@@ -1855,7 +1919,7 @@ void Stepper::pulse_phase_isr() {
|
1855
|
1919
|
|
1856
|
1920
|
// TODO: need to deal with MINIMUM_STEPPER_PULSE over i2s
|
1857
|
1921
|
#if ISR_MULTI_STEPS
|
1858
|
|
- START_HIGH_PULSE();
|
|
1922
|
+ START_TIMED_PULSE();
|
1859
|
1923
|
AWAIT_HIGH_PULSE();
|
1860
|
1924
|
#endif
|
1861
|
1925
|
|
|
@@ -1895,12 +1959,62 @@ void Stepper::pulse_phase_isr() {
|
1895
|
1959
|
#endif
|
1896
|
1960
|
|
1897
|
1961
|
#if ISR_MULTI_STEPS
|
1898
|
|
- if (events_to_do) START_LOW_PULSE();
|
|
1962
|
+ if (events_to_do) START_TIMED_PULSE();
|
1899
|
1963
|
#endif
|
1900
|
1964
|
|
1901
|
1965
|
} while (--events_to_do);
|
1902
|
1966
|
}
|
1903
|
1967
|
|
|
1968
|
+#if ENABLED(INPUT_SHAPING)
|
|
1969
|
+
|
|
1970
|
+ void Stepper::shaping_isr() {
|
|
1971
|
+ xyze_bool_t step_needed{0};
|
|
1972
|
+
|
|
1973
|
+ const bool shapex = TERN0(HAS_SHAPING_X, !shaping_queue.peek_x()),
|
|
1974
|
+ shapey = TERN0(HAS_SHAPING_Y, !shaping_queue.peek_y());
|
|
1975
|
+
|
|
1976
|
+ #if HAS_SHAPING_X
|
|
1977
|
+ if (!shaping_dividend_queue.peek_x()) shaping_x.dividend = shaping_dividend_queue.dequeue_x();
|
|
1978
|
+ #endif
|
|
1979
|
+ #if HAS_SHAPING_Y
|
|
1980
|
+ if (!shaping_dividend_queue.peek_y()) shaping_y.dividend = shaping_dividend_queue.dequeue_y();
|
|
1981
|
+ #endif
|
|
1982
|
+
|
|
1983
|
+ #if HAS_SHAPING_X
|
|
1984
|
+ if (shapex) {
|
|
1985
|
+ shaping_queue.dequeue_x();
|
|
1986
|
+ PULSE_PREP_SHAPING(X, shaping_x.dividend);
|
|
1987
|
+ PULSE_START(X);
|
|
1988
|
+ }
|
|
1989
|
+ #endif
|
|
1990
|
+
|
|
1991
|
+ #if HAS_SHAPING_Y
|
|
1992
|
+ if (shapey) {
|
|
1993
|
+ shaping_queue.dequeue_y();
|
|
1994
|
+ PULSE_PREP_SHAPING(Y, shaping_y.dividend);
|
|
1995
|
+ PULSE_START(Y);
|
|
1996
|
+ }
|
|
1997
|
+ #endif
|
|
1998
|
+
|
|
1999
|
+ TERN_(I2S_STEPPER_STREAM, i2s_push_sample());
|
|
2000
|
+
|
|
2001
|
+ if (shapex || shapey) {
|
|
2002
|
+ #if ISR_MULTI_STEPS
|
|
2003
|
+ USING_TIMED_PULSE();
|
|
2004
|
+ START_TIMED_PULSE();
|
|
2005
|
+ AWAIT_HIGH_PULSE();
|
|
2006
|
+ #endif
|
|
2007
|
+ #if HAS_SHAPING_X
|
|
2008
|
+ if (shapex) PULSE_STOP(X);
|
|
2009
|
+ #endif
|
|
2010
|
+ #if HAS_SHAPING_Y
|
|
2011
|
+ if (shapey) PULSE_STOP(Y);
|
|
2012
|
+ #endif
|
|
2013
|
+ }
|
|
2014
|
+ }
|
|
2015
|
+
|
|
2016
|
+#endif // INPUT_SHAPING
|
|
2017
|
+
|
1904
|
2018
|
// Calculate timer interval, with all limits applied.
|
1905
|
2019
|
uint32_t Stepper::calc_timer_interval(uint32_t step_rate) {
|
1906
|
2020
|
#ifdef CPU_32_BIT
|
|
@@ -2365,12 +2479,56 @@ uint32_t Stepper::block_phase_isr() {
|
2365
|
2479
|
step_event_count = current_block->step_event_count << oversampling;
|
2366
|
2480
|
|
2367
|
2481
|
// Initialize Bresenham delta errors to 1/2
|
|
2482
|
+ #if HAS_SHAPING_X
|
|
2483
|
+ const int32_t old_delta_error_x = delta_error.x;
|
|
2484
|
+ #endif
|
|
2485
|
+ #if HAS_SHAPING_Y
|
|
2486
|
+ const int32_t old_delta_error_y = delta_error.y;
|
|
2487
|
+ #endif
|
2368
|
2488
|
delta_error = TERN_(LIN_ADVANCE, la_delta_error =) -int32_t(step_event_count);
|
2369
|
2489
|
|
2370
|
2490
|
// Calculate Bresenham dividends and divisors
|
2371
|
|
- advance_dividend = current_block->steps << 1;
|
|
2491
|
+ advance_dividend = (current_block->steps << 1).asLong();
|
2372
|
2492
|
advance_divisor = step_event_count << 1;
|
2373
|
2493
|
|
|
2494
|
+ // for input shaped axes, advance_divisor is replaced with 0x40000000
|
|
2495
|
+ // and steps are repeated twice so dividends have to be scaled and halved
|
|
2496
|
+ // and the dividend is directional, i.e. signed
|
|
2497
|
+ TERN_(HAS_SHAPING_X, advance_dividend.x = (uint64_t(current_block->steps.x) << 29) / step_event_count);
|
|
2498
|
+ TERN_(HAS_SHAPING_X, if (TEST(current_block->direction_bits, X_AXIS)) advance_dividend.x *= -1);
|
|
2499
|
+ TERN_(HAS_SHAPING_X, if (!shaping_queue.empty_x()) SET_BIT_TO(current_block->direction_bits, X_AXIS, TEST(last_direction_bits, X_AXIS)));
|
|
2500
|
+ TERN_(HAS_SHAPING_Y, advance_dividend.y = (uint64_t(current_block->steps.y) << 29) / step_event_count);
|
|
2501
|
+ TERN_(HAS_SHAPING_Y, if (TEST(current_block->direction_bits, Y_AXIS)) advance_dividend.y *= -1);
|
|
2502
|
+ TERN_(HAS_SHAPING_Y, if (!shaping_queue.empty_y()) SET_BIT_TO(current_block->direction_bits, Y_AXIS, TEST(last_direction_bits, Y_AXIS)));
|
|
2503
|
+
|
|
2504
|
+ // The scaling operation above introduces rounding errors which must now be removed.
|
|
2505
|
+ // For this segment, there will be step_event_count calls to the Bresenham logic and the same number of echoes.
|
|
2506
|
+ // For each pair of calls to the Bresenham logic, delta_error will increase by advance_dividend modulo 0x20000000
|
|
2507
|
+ // so (e.g. for x) delta_error.x will end up changing by (advance_dividend.x * step_event_count) % 0x20000000.
|
|
2508
|
+ // For a divisor which is a power of 2, modulo is the same as as a bitmask, i.e.
|
|
2509
|
+ // (advance_dividend.x * step_event_count) & 0x1FFFFFFF.
|
|
2510
|
+ // This segment's final change in delta_error should actually be zero so we need to increase delta_error by
|
|
2511
|
+ // 0 - ((advance_dividend.x * step_event_count) & 0x1FFFFFFF)
|
|
2512
|
+ // And this needs to be adjusted to the range -0x10000000 to 0x10000000.
|
|
2513
|
+ // Adding and subtracting 0x10000000 inside the outside the modulo achieves this.
|
|
2514
|
+ TERN_(HAS_SHAPING_X, delta_error.x = old_delta_error_x + 0x10000000L - ((0x10000000L + advance_dividend.x * step_event_count) & 0x1FFFFFFFUL));
|
|
2515
|
+ TERN_(HAS_SHAPING_Y, delta_error.y = old_delta_error_y + 0x10000000L - ((0x10000000L + advance_dividend.y * step_event_count) & 0x1FFFFFFFUL));
|
|
2516
|
+
|
|
2517
|
+ // when there is damping, the signal and its echo have different amplitudes
|
|
2518
|
+ #if ENABLED(HAS_SHAPING_X)
|
|
2519
|
+ const int32_t echo_x = shaping_x.factor * (advance_dividend.x >> 7);
|
|
2520
|
+ #endif
|
|
2521
|
+ #if ENABLED(HAS_SHAPING_Y)
|
|
2522
|
+ const int32_t echo_y = shaping_y.factor * (advance_dividend.y >> 7);
|
|
2523
|
+ #endif
|
|
2524
|
+
|
|
2525
|
+ // plan the change of values for advance_dividend for the input shaping echoes
|
|
2526
|
+ TERN_(INPUT_SHAPING, shaping_dividend_queue.enqueue(TERN0(HAS_SHAPING_X, echo_x), TERN0(HAS_SHAPING_Y, echo_y)));
|
|
2527
|
+
|
|
2528
|
+ // apply the adjustment to the primary signal
|
|
2529
|
+ TERN_(HAS_SHAPING_X, advance_dividend.x -= echo_x);
|
|
2530
|
+ TERN_(HAS_SHAPING_Y, advance_dividend.y -= echo_y);
|
|
2531
|
+
|
2374
|
2532
|
// No step events completed so far
|
2375
|
2533
|
step_events_completed = 0;
|
2376
|
2534
|
|
|
@@ -2485,7 +2643,7 @@ uint32_t Stepper::block_phase_isr() {
|
2485
|
2643
|
// Enforce a minimum duration for STEP pulse ON
|
2486
|
2644
|
#if ISR_PULSE_CONTROL
|
2487
|
2645
|
USING_TIMED_PULSE();
|
2488
|
|
- START_HIGH_PULSE();
|
|
2646
|
+ START_TIMED_PULSE();
|
2489
|
2647
|
AWAIT_HIGH_PULSE();
|
2490
|
2648
|
#endif
|
2491
|
2649
|
|
|
@@ -2816,6 +2974,51 @@ void Stepper::init() {
|
2816
|
2974
|
#endif
|
2817
|
2975
|
}
|
2818
|
2976
|
|
|
2977
|
+#if ENABLED(INPUT_SHAPING)
|
|
2978
|
+ /**
|
|
2979
|
+ * Calculate a fixed point factor to apply to the signal and its echo
|
|
2980
|
+ * when shaping an axis.
|
|
2981
|
+ */
|
|
2982
|
+ void Stepper::set_shaping_damping_ratio(const AxisEnum axis, const float zeta) {
|
|
2983
|
+ // from the damping ratio, get a factor that can be applied to advance_dividend for fixed point maths
|
|
2984
|
+ // for ZV, we use amplitudes 1/(1+K) and K/(1+K) where K = exp(-zeta * M_PI / sqrt(1.0f - zeta * zeta))
|
|
2985
|
+ // which can be converted to 1:7 fixed point with an excellent fit with a 3rd order polynomial
|
|
2986
|
+ float shaping_factor;
|
|
2987
|
+ if (zeta <= 0.0f) shaping_factor = 64.0f;
|
|
2988
|
+ else if (zeta >= 1.0f) shaping_factor = 0.0f;
|
|
2989
|
+ else {
|
|
2990
|
+ shaping_factor = 64.44056192 + -99.02008832 * zeta;
|
|
2991
|
+ const float zeta2 = zeta * zeta;
|
|
2992
|
+ shaping_factor += -7.58095488 * zeta2;
|
|
2993
|
+ const float zeta3 = zeta2 * zeta;
|
|
2994
|
+ shaping_factor += 43.073216 * zeta3;
|
|
2995
|
+ }
|
|
2996
|
+
|
|
2997
|
+ const bool was_on = hal.isr_state();
|
|
2998
|
+ hal.isr_off();
|
|
2999
|
+ TERN_(HAS_SHAPING_X, if (axis == X_AXIS) { shaping_x.factor = floor(shaping_factor); shaping_x.zeta = zeta; })
|
|
3000
|
+ TERN_(HAS_SHAPING_Y, if (axis == Y_AXIS) { shaping_y.factor = floor(shaping_factor); shaping_y.zeta = zeta; })
|
|
3001
|
+ if (was_on) hal.isr_on();
|
|
3002
|
+ }
|
|
3003
|
+
|
|
3004
|
+ float Stepper::get_shaping_damping_ratio(const AxisEnum axis) {
|
|
3005
|
+ TERN_(HAS_SHAPING_X, if (axis == X_AXIS) return shaping_x.zeta);
|
|
3006
|
+ TERN_(HAS_SHAPING_Y, if (axis == Y_AXIS) return shaping_y.zeta);
|
|
3007
|
+ return -1;
|
|
3008
|
+ }
|
|
3009
|
+
|
|
3010
|
+ void Stepper::set_shaping_frequency(const AxisEnum axis, const float freq) {
|
|
3011
|
+ TERN_(HAS_SHAPING_X, if (axis == X_AXIS) { DelayTimeManager::set_delay(axis, float(uint32_t(STEPPER_TIMER_RATE) / 2) / freq); shaping_x.frequency = freq; })
|
|
3012
|
+ TERN_(HAS_SHAPING_Y, if (axis == Y_AXIS) { DelayTimeManager::set_delay(axis, float(uint32_t(STEPPER_TIMER_RATE) / 2) / freq); shaping_y.frequency = freq; })
|
|
3013
|
+ }
|
|
3014
|
+
|
|
3015
|
+ float Stepper::get_shaping_frequency(const AxisEnum axis) {
|
|
3016
|
+ TERN_(HAS_SHAPING_X, if (axis == X_AXIS) return shaping_x.frequency);
|
|
3017
|
+ TERN_(HAS_SHAPING_Y, if (axis == Y_AXIS) return shaping_y.frequency);
|
|
3018
|
+ return -1;
|
|
3019
|
+ }
|
|
3020
|
+#endif
|
|
3021
|
+
|
2819
|
3022
|
/**
|
2820
|
3023
|
* Set the stepper positions directly in steps
|
2821
|
3024
|
*
|
|
@@ -3021,7 +3224,7 @@ void Stepper::report_positions() {
|
3021
|
3224
|
|
3022
|
3225
|
#if EXTRA_CYCLES_BABYSTEP > 20
|
3023
|
3226
|
#define _SAVE_START() const hal_timer_t pulse_start = HAL_timer_get_count(MF_TIMER_PULSE)
|
3024
|
|
- #define _PULSE_WAIT() while (EXTRA_CYCLES_BABYSTEP > (uint32_t)(HAL_timer_get_count(MF_TIMER_PULSE) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ }
|
|
3227
|
+ #define _PULSE_WAIT() while (EXTRA_CYCLES_BABYSTEP > uint32_t(HAL_timer_get_count(MF_TIMER_PULSE) - pulse_start) * (PULSE_TIMER_PRESCALE)) { /* nada */ }
|
3025
|
3228
|
#else
|
3026
|
3229
|
#define _SAVE_START() NOOP
|
3027
|
3230
|
#if EXTRA_CYCLES_BABYSTEP > 0
|