diff --git a/dda.c b/dda.c index be4308708..44b5a6863 100644 --- a/dda.c +++ b/dda.c @@ -116,7 +116,10 @@ void dda_new_startpoint(void) { startpoint_steps.axis[E] = um_to_steps(startpoint.axis[E], E); } -/*! CREATE a dda given current_position and a target, save to passed location so we can write directly into the queue +/** + Create a DDA using startpoint, startpoint_steps and a target, save to passed + location so we can write directly into the queue. + \param *dda pointer to a dda_queue entry to overwrite \param *target the target position of this move @@ -126,8 +129,9 @@ void dda_new_startpoint(void) { It also pre-fills any data that the selected accleration algorithm needs, and can be pre-computed for the whole move. - This algorithm is probably the main limiting factor to print speed in terms of firmware limitations - * + This algorithm is the main limiting factor when queuing movements and can + become a limitation to print speed if there are lots of tiny, fast movements. + * Regarding lookahead, we can distinguish everything into these cases: * * 1. Standard movement. To be joined with the previous move. @@ -278,6 +282,7 @@ void dda_create(DDA *dda, const TARGET *target) { if (dda->total_steps == 0) { dda->nullmove = 1; + startpoint.F = dda->endpoint.F; } else { // get steppers ready to go @@ -467,16 +472,16 @@ void dda_create(DDA *dda, const TARGET *target) { if (dda->c < c_limit) dda->c = c_limit; #endif + + // next dda starts where we finish + memcpy(&startpoint, &dda->endpoint, sizeof(TARGET)); + #ifdef LOOKAHEAD + prev_dda = dda; + #endif } /* ! dda->total_steps == 0 */ if (DEBUG_DDA && (debug_flags & DEBUG_DDA)) serial_writestr_P(PSTR("] }\n")); - - // next dda starts where we finish - memcpy(&startpoint, &dda->endpoint, sizeof(TARGET)); - #ifdef LOOKAHEAD - prev_dda = dda; - #endif } /*! Start a prepared DDA @@ -498,7 +503,6 @@ void dda_start(DDA *dda) { dda->endpoint.axis[X], dda->endpoint.axis[Y], dda->endpoint.axis[Z], dda->endpoint.F); - if ( ! dda->nullmove) { // get ready to go psu_timeout = 0; #ifdef Z_AUTODISABLE @@ -538,10 +542,6 @@ void dda_start(DDA *dda) { // set timeout for first step timer_set(dda->c, 0); } - // else just a speed change, keep dda->live = 0 - - current_position.F = dda->endpoint.F; -} /** \brief Do per-step movement maintenance. @@ -971,11 +971,13 @@ void update_current_position() { current_position.axis[E] = axis_um; } - // current_position.F is updated in dda_start() + current_position.F = dda->endpoint.F; } else { for (i = X; i < AXIS_COUNT; i++) { current_position.axis[i] = startpoint.axis[i]; } + current_position.F = startpoint.F; } + } diff --git a/dda_lookahead.c b/dda_lookahead.c index 8b8f7a464..d0ffbd8bf 100644 --- a/dda_lookahead.c +++ b/dda_lookahead.c @@ -56,8 +56,8 @@ void dda_find_crossing_speed(DDA *prev, DDA *current) { axes_int32_t prevF, currF; enum axis_e i; - // Bail out if there's nothing to join (e.g. G1 F1500). - if ( ! prev || prev->nullmove) + // Bail out if there's nothing to join (e.g. first movement after a pause). + if ( ! prev) return; // We always look at the smaller of both combined speeds, @@ -180,8 +180,8 @@ void dda_join_moves(DDA *prev, DDA *current) { moveno++; #endif - // Bail out if there's nothing to join (e.g. G1 F1500). - if ( ! prev || prev->nullmove || current->crossF == 0) + // Bail out if there's nothing to join. + if ( ! prev || current->crossF == 0) return; // Show the proposed crossing speed - this might get adjusted below. diff --git a/dda_queue.c b/dda_queue.c index 54efca9d3..9e619bc34 100644 --- a/dda_queue.c +++ b/dda_queue.c @@ -63,7 +63,7 @@ DDA *queue_current_movement() { ATOMIC_START current = &movebuffer[mb_tail]; - if ( ! current->live || current->waitfor_temp || current->nullmove) + if ( ! current->live || current->waitfor_temp) current = NULL; ATOMIC_END @@ -125,23 +125,32 @@ void enqueue_home(TARGET *t, uint8_t endstop_check, uint8_t endstop_stop_cond) { } dda_create(new_movebuffer, t); - // make certain all writes to global memory - // are flushed before modifying mb_head. - MEMORY_BARRIER(); + /** + It's pointless to queue up movements which don't actually move the stepper, + e.g. pure velocity changes or movements shorter than a single motor step. - mb_head = h; + That said, accept movements which do move the steppers by forwarding + mb_head. Also kick off movements if it's the first movement after a pause. + */ + if ( ! new_movebuffer->nullmove) { + // make certain all writes to global memory + // are flushed before modifying mb_head. + MEMORY_BARRIER(); - uint8_t isdead; + mb_head = h; - ATOMIC_START - isdead = (movebuffer[mb_tail].live == 0); - ATOMIC_END + uint8_t isdead; - if (isdead) { - timer_reset(); - next_move(); - // Compensate for the cli() in timer_set(). - sei(); + ATOMIC_START + isdead = (movebuffer[mb_tail].live == 0); + ATOMIC_END + + if (isdead) { + timer_reset(); + next_move(); + // Compensate for the cli() in timer_set(). + sei(); + } } } @@ -154,7 +163,8 @@ void enqueue_home(TARGET *t, uint8_t endstop_check, uint8_t endstop_stop_cond) { /// move buffer was dead in the non-interrupt case (which indicates that the /// timer interrupt is disabled). void next_move() { - while ((queue_empty() == 0) && (movebuffer[mb_tail].live == 0)) { + + if (queue_empty() == 0) { // Tail must be set before calling timer_set(), as timer_set() reenables // the timer interrupt, potentially exposing mb_tail to the timer // interrupt routine.