G6 Direct Stepping (#17853)
This commit is contained in:
@ -151,6 +151,11 @@ float Planner::steps_to_mm[XYZE_N]; // (mm) Millimeters per step
|
||||
uint8_t Planner::last_extruder = 0; // Respond to extruder change
|
||||
#endif
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
uint32_t Planner::last_page_step_rate = 0;
|
||||
xyze_bool_t Planner::last_page_dir{0};
|
||||
#endif
|
||||
|
||||
#if EXTRUDERS
|
||||
int16_t Planner::flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100); // Extrusion factor for each extruder
|
||||
float Planner::e_factor[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(1.0f); // The flow percentage and volumetric multiplier combine to scale E movement
|
||||
@ -235,6 +240,10 @@ void Planner::init() {
|
||||
TERN_(ABL_PLANAR, bed_level_matrix.set_to_identity());
|
||||
clear_block_buffer();
|
||||
delay_before_delivering = 0;
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
last_page_step_rate = 0;
|
||||
last_page_dir.reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLED(S_CURVE_ACCELERATION)
|
||||
@ -906,7 +915,7 @@ void Planner::calculate_trapezoid_for_block(block_t* const block, const float &e
|
||||
streaming operating conditions. Use for planning optimizations by avoiding recomputing parts of the
|
||||
planner buffer that don't change with the addition of a new block, as describe above. In addition,
|
||||
this block can never be less than block_buffer_tail and will always be pushed forward and maintain
|
||||
this requirement when encountered by the Planner::discard_current_block() routine during a cycle.
|
||||
this requirement when encountered by the Planner::release_current_block() routine during a cycle.
|
||||
|
||||
NOTE: Since the planner only computes on what's in the planner buffer, some motions with lots of short
|
||||
line segments, like G2/3 arcs or complex curves, may seem to move slow. This is because there simply isn't
|
||||
@ -994,8 +1003,8 @@ void Planner::reverse_pass() {
|
||||
// Perform the reverse pass
|
||||
block_t *current = &block_buffer[block_index];
|
||||
|
||||
// Only consider non sync blocks
|
||||
if (!TEST(current->flag, BLOCK_BIT_SYNC_POSITION)) {
|
||||
// Only consider non sync and page blocks
|
||||
if (!TEST(current->flag, BLOCK_BIT_SYNC_POSITION) && !IS_PAGE(current)) {
|
||||
reverse_pass_kernel(current, next);
|
||||
next = current;
|
||||
}
|
||||
@ -1089,8 +1098,8 @@ void Planner::forward_pass() {
|
||||
// Perform the forward pass
|
||||
block = &block_buffer[block_index];
|
||||
|
||||
// Skip SYNC blocks
|
||||
if (!TEST(block->flag, BLOCK_BIT_SYNC_POSITION)) {
|
||||
// Skip SYNC and page blocks
|
||||
if (!TEST(block->flag, BLOCK_BIT_SYNC_POSITION) && !IS_PAGE(block)) {
|
||||
// If there's no previous block or the previous block is not
|
||||
// BUSY (thus, modifiable) run the forward_pass_kernel. Otherwise,
|
||||
// the previous block became BUSY, so assume the current block's
|
||||
@ -1139,8 +1148,8 @@ void Planner::recalculate_trapezoids() {
|
||||
|
||||
next = &block_buffer[block_index];
|
||||
|
||||
// Skip sync blocks
|
||||
if (!TEST(next->flag, BLOCK_BIT_SYNC_POSITION)) {
|
||||
// Skip sync and page blocks
|
||||
if (!TEST(next->flag, BLOCK_BIT_SYNC_POSITION) && !IS_PAGE(next)) {
|
||||
next_entry_speed = SQRT(next->entry_speed_sqr);
|
||||
|
||||
if (block) {
|
||||
@ -2717,6 +2726,69 @@ bool Planner::buffer_line(const float &rx, const float &ry, const float &rz, con
|
||||
#endif
|
||||
} // buffer_line()
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
|
||||
void Planner::buffer_page(const page_idx_t page_idx, const uint8_t extruder, const uint16_t num_steps) {
|
||||
if (!last_page_step_rate) {
|
||||
kill(GET_TEXT(MSG_BAD_PAGE_SPEED));
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t next_buffer_head;
|
||||
block_t * const block = get_next_free_block(next_buffer_head);
|
||||
|
||||
block->flag = BLOCK_FLAG_IS_PAGE;
|
||||
|
||||
#if FAN_COUNT > 0
|
||||
FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i];
|
||||
#endif
|
||||
|
||||
#if EXTRUDERS > 1
|
||||
block->extruder = extruder;
|
||||
#endif
|
||||
|
||||
block->page_idx = page_idx;
|
||||
|
||||
block->step_event_count = num_steps;
|
||||
block->initial_rate =
|
||||
block->final_rate =
|
||||
block->nominal_rate = last_page_step_rate; // steps/s
|
||||
|
||||
block->accelerate_until = 0;
|
||||
block->decelerate_after = block->step_event_count;
|
||||
|
||||
// Will be set to last direction later if directional format.
|
||||
block->direction_bits = 0;
|
||||
|
||||
#define PAGE_UPDATE_DIR(AXIS) \
|
||||
if (!last_page_dir[_AXIS(AXIS)]) SBI(block->direction_bits, _AXIS(AXIS));
|
||||
|
||||
if (!DirectStepping::Config::DIRECTIONAL) {
|
||||
PAGE_UPDATE_DIR(X);
|
||||
PAGE_UPDATE_DIR(Y);
|
||||
PAGE_UPDATE_DIR(Z);
|
||||
PAGE_UPDATE_DIR(E);
|
||||
}
|
||||
|
||||
// If this is the first added movement, reload the delay, otherwise, cancel it.
|
||||
if (block_buffer_head == block_buffer_tail) {
|
||||
// If it was the first queued block, restart the 1st block delivery delay, to
|
||||
// give the planner an opportunity to queue more movements and plan them
|
||||
// As there are no queued movements, the Stepper ISR will not touch this
|
||||
// variable, so there is no risk setting this here (but it MUST be done
|
||||
// before the following line!!)
|
||||
delay_before_delivering = BLOCK_DELAY_FOR_1ST_MOVE;
|
||||
}
|
||||
|
||||
// Move buffer head
|
||||
block_buffer_head = next_buffer_head;
|
||||
|
||||
enable_all_steppers();
|
||||
stepper.wake_up();
|
||||
}
|
||||
|
||||
#endif // DIRECT_STEPPING
|
||||
|
||||
/**
|
||||
* Directly set the planner ABC position (and stepper positions)
|
||||
* converting mm (or angles for SCARA) into steps.
|
||||
|
@ -66,6 +66,13 @@
|
||||
#include "../feature/spindle_laser_types.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
#include "../feature/direct_stepping.h"
|
||||
#define IS_PAGE(B) TEST(B->flag, BLOCK_BIT_IS_PAGE)
|
||||
#else
|
||||
#define IS_PAGE(B) false
|
||||
#endif
|
||||
|
||||
// Feedrate for manual moves
|
||||
#ifdef MANUAL_FEEDRATE
|
||||
constexpr xyze_feedrate_t _mf = MANUAL_FEEDRATE,
|
||||
@ -90,13 +97,21 @@ enum BlockFlagBit : char {
|
||||
|
||||
// Sync the stepper counts from the block
|
||||
BLOCK_BIT_SYNC_POSITION
|
||||
|
||||
// Direct stepping page
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
, BLOCK_BIT_IS_PAGE
|
||||
#endif
|
||||
};
|
||||
|
||||
enum BlockFlag : char {
|
||||
BLOCK_FLAG_RECALCULATE = _BV(BLOCK_BIT_RECALCULATE),
|
||||
BLOCK_FLAG_NOMINAL_LENGTH = _BV(BLOCK_BIT_NOMINAL_LENGTH),
|
||||
BLOCK_FLAG_CONTINUED = _BV(BLOCK_BIT_CONTINUED),
|
||||
BLOCK_FLAG_SYNC_POSITION = _BV(BLOCK_BIT_SYNC_POSITION)
|
||||
BLOCK_FLAG_RECALCULATE = _BV(BLOCK_BIT_RECALCULATE)
|
||||
, BLOCK_FLAG_NOMINAL_LENGTH = _BV(BLOCK_BIT_NOMINAL_LENGTH)
|
||||
, BLOCK_FLAG_CONTINUED = _BV(BLOCK_BIT_CONTINUED)
|
||||
, BLOCK_FLAG_SYNC_POSITION = _BV(BLOCK_BIT_SYNC_POSITION)
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
, BLOCK_FLAG_IS_PAGE = _BV(BLOCK_BIT_IS_PAGE)
|
||||
#endif
|
||||
};
|
||||
|
||||
#if ENABLED(LASER_POWER_INLINE)
|
||||
@ -180,6 +195,10 @@ typedef struct block_t {
|
||||
final_rate, // The minimal rate at exit
|
||||
acceleration_steps_per_s2; // acceleration steps/sec^2
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
page_idx_t page_idx; // Page index used for direct stepping
|
||||
#endif
|
||||
|
||||
#if HAS_CUTTER
|
||||
cutter_power_t cutter_power; // Power level for Spindle, Laser, etc.
|
||||
#endif
|
||||
@ -296,6 +315,11 @@ class Planner {
|
||||
static uint8_t last_extruder; // Respond to extruder change
|
||||
#endif
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
static uint32_t last_page_step_rate; // Last page step rate given
|
||||
static xyze_bool_t last_page_dir; // Last page direction given
|
||||
#endif
|
||||
|
||||
#if EXTRUDERS
|
||||
static int16_t flow_percentage[EXTRUDERS]; // Extrusion factor for each extruder
|
||||
static float e_factor[EXTRUDERS]; // The flow percentage and volumetric multiplier combine to scale E movement
|
||||
@ -726,6 +750,10 @@ class Planner {
|
||||
);
|
||||
}
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
static void buffer_page(const page_idx_t page_idx, const uint8_t extruder, const uint16_t num_steps);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the planner.position and individual stepper positions.
|
||||
* Used by G92, G28, G29, and other procedures.
|
||||
@ -811,10 +839,10 @@ class Planner {
|
||||
static block_t* get_current_block();
|
||||
|
||||
/**
|
||||
* "Discard" the block and "release" the memory.
|
||||
* "Release" the current block so its slot can be reused.
|
||||
* Called when the current block is no longer needed.
|
||||
*/
|
||||
FORCE_INLINE static void discard_current_block() {
|
||||
FORCE_INLINE static void release_current_block() {
|
||||
if (has_blocks_queued())
|
||||
block_buffer_tail = next_block_index(block_buffer_tail);
|
||||
}
|
||||
|
@ -230,6 +230,10 @@ uint32_t Stepper::advance_divisor = 0,
|
||||
uint32_t Stepper::nextBabystepISR = BABYSTEP_NEVER;
|
||||
#endif
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
page_step_state_t Stepper::page_step_state;
|
||||
#endif
|
||||
|
||||
int32_t Stepper::ticks_nominal = -1;
|
||||
#if DISABLED(S_CURVE_ACCELERATION)
|
||||
uint32_t Stepper::acc_step_rate; // needed for deceleration start point
|
||||
@ -1520,11 +1524,7 @@ void Stepper::pulse_phase_isr() {
|
||||
// If we must abort the current block, do so!
|
||||
if (abort_current_block) {
|
||||
abort_current_block = false;
|
||||
if (current_block) {
|
||||
axis_did_move = 0;
|
||||
current_block = nullptr;
|
||||
planner.discard_current_block();
|
||||
}
|
||||
if (current_block) discard_current_block();
|
||||
}
|
||||
|
||||
// If there is no current block, do nothing
|
||||
@ -1558,46 +1558,160 @@ void Stepper::pulse_phase_isr() {
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
// Start an active pulse, if Bresenham says so, and update position
|
||||
// Start an active pulse if needed
|
||||
#define PULSE_START(AXIS) do{ \
|
||||
if (step_needed[_AXIS(AXIS)]) { \
|
||||
_APPLY_STEP(AXIS, !_INVERT_STEP_PIN(AXIS), 0); \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
// Stop an active pulse, if any, and adjust error term
|
||||
// Stop an active pulse if needed
|
||||
#define PULSE_STOP(AXIS) do { \
|
||||
if (step_needed[_AXIS(AXIS)]) { \
|
||||
_APPLY_STEP(AXIS, _INVERT_STEP_PIN(AXIS), 0); \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
// Determine if pulses are needed
|
||||
#if HAS_X_STEP
|
||||
PULSE_PREP(X);
|
||||
#endif
|
||||
#if HAS_Y_STEP
|
||||
PULSE_PREP(Y);
|
||||
#endif
|
||||
#if HAS_Z_STEP
|
||||
PULSE_PREP(Z);
|
||||
#endif
|
||||
// Direct Stepping page?
|
||||
const bool is_page = IS_PAGE(current_block);
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
|
||||
if (is_page) {
|
||||
|
||||
#if STEPPER_PAGE_FORMAT == SP_4x4D_128
|
||||
|
||||
#define PAGE_SEGMENT_UPDATE(AXIS, VALUE, MID) do{ \
|
||||
if ((VALUE) == MID) {} \
|
||||
else if ((VALUE) < MID) SBI(dm, _AXIS(AXIS)); \
|
||||
else CBI(dm, _AXIS(AXIS)); \
|
||||
page_step_state.sd[_AXIS(AXIS)] = VALUE; \
|
||||
page_step_state.bd[_AXIS(AXIS)] += VALUE; \
|
||||
}while(0)
|
||||
|
||||
#define PAGE_PULSE_PREP(AXIS) do{ \
|
||||
step_needed[_AXIS(AXIS)] = \
|
||||
pgm_read_byte(&segment_table[page_step_state.sd[_AXIS(AXIS)]][page_step_state.segment_steps & 0x7]); \
|
||||
}while(0)
|
||||
|
||||
switch (page_step_state.segment_steps) {
|
||||
case 8:
|
||||
page_step_state.segment_idx += 2;
|
||||
page_step_state.segment_steps = 0;
|
||||
// fallthru
|
||||
case 0: {
|
||||
const uint8_t low = page_step_state.page[page_step_state.segment_idx],
|
||||
high = page_step_state.page[page_step_state.segment_idx + 1];
|
||||
uint8_t dm = last_direction_bits;
|
||||
|
||||
PAGE_SEGMENT_UPDATE(X, low >> 4, 7);
|
||||
PAGE_SEGMENT_UPDATE(Y, low & 0xF, 7);
|
||||
PAGE_SEGMENT_UPDATE(Z, high >> 4, 7);
|
||||
PAGE_SEGMENT_UPDATE(E, high & 0xF, 7);
|
||||
|
||||
if (dm != last_direction_bits) {
|
||||
last_direction_bits = dm;
|
||||
set_directions();
|
||||
}
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
PAGE_PULSE_PREP(X),
|
||||
PAGE_PULSE_PREP(Y),
|
||||
PAGE_PULSE_PREP(Z),
|
||||
PAGE_PULSE_PREP(E);
|
||||
|
||||
page_step_state.segment_steps++;
|
||||
|
||||
#elif STEPPER_PAGE_FORMAT == SP_4x2_256
|
||||
|
||||
#define PAGE_SEGMENT_UPDATE(AXIS, VALUE) \
|
||||
page_step_state.sd[_AXIS(AXIS)] = VALUE; \
|
||||
page_step_state.bd[_AXIS(AXIS)] += VALUE;
|
||||
|
||||
#define PAGE_PULSE_PREP(AXIS) do{ \
|
||||
step_needed[_AXIS(AXIS)] = \
|
||||
pgm_read_byte(&segment_table[page_step_state.sd[_AXIS(AXIS)]][page_step_state.segment_steps & 0x3]); \
|
||||
}while(0)
|
||||
|
||||
switch (page_step_state.segment_steps) {
|
||||
case 4:
|
||||
page_step_state.segment_idx++;
|
||||
page_step_state.segment_steps = 0;
|
||||
// fallthru
|
||||
case 0: {
|
||||
const uint8_t b = page_step_state.page[page_step_state.segment_idx];
|
||||
PAGE_SEGMENT_UPDATE(X, (b >> 6) & 0x3);
|
||||
PAGE_SEGMENT_UPDATE(Y, (b >> 4) & 0x3);
|
||||
PAGE_SEGMENT_UPDATE(Z, (b >> 2) & 0x3);
|
||||
PAGE_SEGMENT_UPDATE(E, (b >> 0) & 0x3);
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
PAGE_PULSE_PREP(X);
|
||||
PAGE_PULSE_PREP(Y);
|
||||
PAGE_PULSE_PREP(Z);
|
||||
PAGE_PULSE_PREP(E);
|
||||
|
||||
page_step_state.segment_steps++;
|
||||
|
||||
#elif STEPPER_PAGE_FORMAT == SP_4x1_512
|
||||
|
||||
#define PAGE_PULSE_PREP(AXIS, BITS) do{ \
|
||||
step_needed[_AXIS(AXIS)] = (steps >> BITS) & 0x1; \
|
||||
if (step_needed[_AXIS(AXIS)]) \
|
||||
page_step_state.bd[_AXIS(AXIS)]++; \
|
||||
}while(0)
|
||||
|
||||
uint8_t steps = page_step_state.page[page_step_state.segment_idx >> 1];
|
||||
|
||||
if (page_step_state.segment_idx & 0x1) steps >>= 4;
|
||||
|
||||
PAGE_PULSE_PREP(X, 3);
|
||||
PAGE_PULSE_PREP(Y, 2);
|
||||
PAGE_PULSE_PREP(Z, 1);
|
||||
PAGE_PULSE_PREP(E, 0);
|
||||
|
||||
page_step_state.segment_idx++;
|
||||
|
||||
#if EITHER(LIN_ADVANCE, MIXING_EXTRUDER)
|
||||
delta_error.e += advance_dividend.e;
|
||||
if (delta_error.e >= 0) {
|
||||
count_position.e += count_direction.e;
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
delta_error.e -= advance_divisor;
|
||||
// Don't step E here - But remember the number of steps to perform
|
||||
motor_direction(E_AXIS) ? --LA_steps : ++LA_steps;
|
||||
#else
|
||||
step_needed.e = true;
|
||||
#error "Unknown direct stepping page format!"
|
||||
#endif
|
||||
}
|
||||
#elif HAS_E0_STEP
|
||||
PULSE_PREP(E);
|
||||
#endif
|
||||
|
||||
#endif // DIRECT_STEPPING
|
||||
|
||||
if (!is_page) {
|
||||
// Determine if pulses are needed
|
||||
#if HAS_X_STEP
|
||||
PULSE_PREP(X);
|
||||
#endif
|
||||
#if HAS_Y_STEP
|
||||
PULSE_PREP(Y);
|
||||
#endif
|
||||
#if HAS_Z_STEP
|
||||
PULSE_PREP(Z);
|
||||
#endif
|
||||
|
||||
#if EITHER(LIN_ADVANCE, MIXING_EXTRUDER)
|
||||
delta_error.e += advance_dividend.e;
|
||||
if (delta_error.e >= 0) {
|
||||
count_position.e += count_direction.e;
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
delta_error.e -= advance_divisor;
|
||||
// Don't step E here - But remember the number of steps to perform
|
||||
motor_direction(E_AXIS) ? --LA_steps : ++LA_steps;
|
||||
#else
|
||||
step_needed.e = true;
|
||||
#endif
|
||||
}
|
||||
#elif HAS_E0_STEP
|
||||
PULSE_PREP(E);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ISR_MULTI_STEPS
|
||||
if (firstStep)
|
||||
@ -1676,14 +1790,28 @@ uint32_t Stepper::block_phase_isr() {
|
||||
// If there is a current block
|
||||
if (current_block) {
|
||||
|
||||
// If current block is finished, reset pointer
|
||||
// If current block is finished, reset pointer and finalize state
|
||||
if (step_events_completed >= step_event_count) {
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
#if STEPPER_PAGE_FORMAT == SP_4x4D_128
|
||||
#define PAGE_SEGMENT_UPDATE_POS(AXIS) \
|
||||
count_position[_AXIS(AXIS)] += page_step_state.bd[_AXIS(AXIS)] - 128 * 7;
|
||||
#elif STEPPER_PAGE_FORMAT == SP_4x1_512 || STEPPER_PAGE_FORMAT == SP_4x2_256
|
||||
#define PAGE_SEGMENT_UPDATE_POS(AXIS) \
|
||||
count_position[_AXIS(AXIS)] += page_step_state.bd[_AXIS(AXIS)] * count_direction[_AXIS(AXIS)];
|
||||
#endif
|
||||
|
||||
if (IS_PAGE(current_block)) {
|
||||
PAGE_SEGMENT_UPDATE_POS(X);
|
||||
PAGE_SEGMENT_UPDATE_POS(Y);
|
||||
PAGE_SEGMENT_UPDATE_POS(Z);
|
||||
PAGE_SEGMENT_UPDATE_POS(E);
|
||||
}
|
||||
#endif
|
||||
#ifdef FILAMENT_RUNOUT_DISTANCE_MM
|
||||
runout.block_completed(current_block);
|
||||
#endif
|
||||
axis_did_move = 0;
|
||||
current_block = nullptr;
|
||||
planner.discard_current_block();
|
||||
discard_current_block();
|
||||
}
|
||||
else {
|
||||
// Step events not completed yet...
|
||||
@ -1867,7 +1995,7 @@ uint32_t Stepper::block_phase_isr() {
|
||||
// Sync block? Sync the stepper counts and return
|
||||
while (TEST(current_block->flag, BLOCK_BIT_SYNC_POSITION)) {
|
||||
_set_position(current_block->position);
|
||||
planner.discard_current_block();
|
||||
discard_current_block();
|
||||
|
||||
// Try to get a new block
|
||||
if (!(current_block = planner.get_current_block()))
|
||||
@ -1878,6 +2006,23 @@ uint32_t Stepper::block_phase_isr() {
|
||||
|
||||
TERN_(POWER_LOSS_RECOVERY, recovery.info.sdpos = current_block->sdpos);
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
if (IS_PAGE(current_block)) {
|
||||
page_step_state.segment_steps = 0;
|
||||
page_step_state.segment_idx = 0;
|
||||
page_step_state.page = page_manager.get_page(current_block->page_idx);
|
||||
page_step_state.bd.reset();
|
||||
|
||||
if (DirectStepping::Config::DIRECTIONAL)
|
||||
current_block->direction_bits = last_direction_bits;
|
||||
|
||||
if (!page_step_state.page) {
|
||||
discard_current_block();
|
||||
return interval;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Flag all moving axes for proper endstop handling
|
||||
|
||||
#if IS_CORE
|
||||
|
@ -334,6 +334,10 @@ class Stepper {
|
||||
static uint32_t nextBabystepISR;
|
||||
#endif
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
static page_step_state_t page_step_state;
|
||||
#endif
|
||||
|
||||
static int32_t ticks_nominal;
|
||||
#if DISABLED(S_CURVE_ACCELERATION)
|
||||
static uint32_t acc_step_rate; // needed for deceleration start point
|
||||
@ -426,6 +430,17 @@ class Stepper {
|
||||
static void report_a_position(const xyz_long_t &pos);
|
||||
static void report_positions();
|
||||
|
||||
// Discard current block and free any resources
|
||||
FORCE_INLINE static void discard_current_block() {
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
if (IS_PAGE(current_block))
|
||||
page_manager.free_page(current_block->page_idx);
|
||||
#endif
|
||||
current_block = nullptr;
|
||||
axis_did_move = 0;
|
||||
planner.release_current_block();
|
||||
}
|
||||
|
||||
// Quickly stop all steppers
|
||||
FORCE_INLINE static void quick_stop() { abort_current_block = true; }
|
||||
|
||||
|
Reference in New Issue
Block a user