G6 Direct Stepping (#17853)

This commit is contained in:
Colin Godsey
2020-05-11 18:22:41 -06:00
committed by GitHub
parent 174e41c17d
commit 8a22ef0c83
17 changed files with 859 additions and 64 deletions

View File

@@ -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