diff --git a/dda.c b/dda.c index 4f223da..edabb81 100644 --- a/dda.c +++ b/dda.c @@ -19,7 +19,7 @@ #include "debug.h" #include "sersendf.h" #include "pinio.h" -#include "config.h" +#include "memory_barrier.h" //#include "graycode.c" #ifdef DC_EXTRUDER @@ -461,35 +461,9 @@ void dda_start(DDA *dda) { Finally we de-assert any asserted step pins. */ void dda_step(DDA *dda) { - uint8_t endstop_stop; ///< Stop due to endstop trigger - uint8_t endstop_not_done = 0; ///< Which axes haven't finished homing - -#if defined X_MIN_PIN || defined X_MAX_PIN - if (dda->endstop_check & 0x1) { -#if defined X_MIN_PIN - if (x_min() == dda->endstop_stop_cond) - move_state.debounce_count_xmin++; - else - move_state.debounce_count_xmin = 0; -#endif - -#if defined X_MAX_PIN - if (x_max() == dda->endstop_stop_cond) - move_state.debounce_count_xmax++; - else - move_state.debounce_count_xmax = 0; -#endif - - endstop_stop = move_state.debounce_count_xmin >= ENDSTOP_STEPS || - move_state.debounce_count_xmax >= ENDSTOP_STEPS; - if (!endstop_stop) - endstop_not_done |= 0x1; - } else -#endif - endstop_stop = 0; #if ! defined ACCELERATION_TEMPORAL - if ((move_state.x_steps) && ! endstop_stop) { + if (move_state.x_steps) { move_state.x_counter -= dda->x_delta; if (move_state.x_counter < 0) { x_step(); @@ -498,7 +472,7 @@ void dda_step(DDA *dda) { } } #else // ACCELERATION_TEMPORAL - if ((dda->axis_to_step == 'x') && ! endstop_stop) { + if (dda->axis_to_step == 'x') { x_step(); move_state.x_steps--; move_state.x_time += dda->x_step_interval; @@ -506,32 +480,8 @@ void dda_step(DDA *dda) { } #endif -#if defined Y_MIN_PIN || defined Y_MAX_PIN - if (dda->endstop_check & 0x2) { -#if defined Y_MIN_PIN - if (y_min() == dda->endstop_stop_cond) - move_state.debounce_count_ymin++; - else - move_state.debounce_count_ymin = 0; -#endif - -#if defined Y_MAX_PIN - if (y_max() == dda->endstop_stop_cond) - move_state.debounce_count_ymax++; - else - move_state.debounce_count_ymax = 0; -#endif - - endstop_stop = move_state.debounce_count_ymin >= ENDSTOP_STEPS || - move_state.debounce_count_ymax >= ENDSTOP_STEPS; - if (!endstop_stop) - endstop_not_done |= 0x2; - } else -#endif - endstop_stop = 0; - #if ! defined ACCELERATION_TEMPORAL - if ((move_state.y_steps) && ! endstop_stop) { + if (move_state.y_steps) { move_state.y_counter -= dda->y_delta; if (move_state.y_counter < 0) { y_step(); @@ -548,32 +498,8 @@ void dda_step(DDA *dda) { } #endif -#if defined Z_MIN_PIN || defined Z_MAX_PIN - if (dda->endstop_check & 0x4) { -#if defined Z_MIN_PIN - if (z_min() == dda->endstop_stop_cond) - move_state.debounce_count_zmin++; - else - move_state.debounce_count_zmin = 0; -#endif - -#if defined Z_MAX_PIN - if (z_max() == dda->endstop_stop_cond) - move_state.debounce_count_zmax++; - else - move_state.debounce_count_zmax = 0; -#endif - - endstop_stop = move_state.debounce_count_zmin >= ENDSTOP_STEPS || - move_state.debounce_count_zmax >= ENDSTOP_STEPS; - if (!endstop_stop) - endstop_not_done |= 0x4; - } else -#endif - endstop_stop = 0; - #if ! defined ACCELERATION_TEMPORAL - if ((move_state.z_steps) && ! endstop_stop) { + if (move_state.z_steps) { move_state.z_counter -= dda->z_delta; if (move_state.z_counter < 0) { z_step(); @@ -582,7 +508,7 @@ void dda_step(DDA *dda) { } } #else // ACCELERATION_TEMPORAL - if ((dda->axis_to_step == 'z') && ! endstop_stop) { + if (dda->axis_to_step == 'z') { z_step(); move_state.z_steps--; move_state.z_time += dda->z_step_interval; @@ -673,6 +599,17 @@ void dda_step(DDA *dda) { // move_state.c, move_state.step_no, move_state.y_steps); } move_state.step_no++; + + #ifdef ACCELERATION_RAMPING + // This is a hack which deals with movements with an unknown number of + // acceleration steps. dda_create() sets a very high number, then. + if (move_state.c < dda->c_min && + dda->rampup_steps > move_state.step_no + 5) { + dda->rampup_steps = move_state.step_no; + dda->rampdown_steps = dda->total_steps - dda->rampup_steps; + } + #endif + // Print the number of steps actually needed for ramping up // Needed for comparing the number with the one calculated in dda_create() //static char printed = 0; @@ -689,13 +626,6 @@ void dda_step(DDA *dda) { // move_state.c, dda->c_min, move_state.n); #endif - // TODO: If we stop axes individually, could we home two or more axes at the same time? - if (dda->endstop_check != 0x0 && endstop_not_done == 0x0) { - move_state.x_steps = move_state.y_steps = move_state.z_steps = move_state.e_steps = 0; - endstops_off(); - // as we stop without ramping down, we have to re-init our ramping here - dda_init(); - } #ifdef ACCELERATION_TEMPORAL /** How is this ACCELERATION TEMPORAL expected to work? @@ -737,9 +667,10 @@ void dda_step(DDA *dda) { dda->c <<= 8; #endif - // If there are no steps left, we have finished. - if (move_state.x_steps == 0 && move_state.y_steps == 0 && - move_state.z_steps == 0 && move_state.e_steps == 0) { + // If there are no steps left or an endstop stop happened, we have finished. + if ((move_state.x_steps == 0 && move_state.y_steps == 0 && + move_state.z_steps == 0 && move_state.e_steps == 0) || + (dda->endstop_check && move_state.n == -3)) { dda->live = 0; #ifdef LOOKAHEAD // If look-ahead was using this move, it could have missed our activation: @@ -773,6 +704,112 @@ void dda_step(DDA *dda) { unstep(); } +/*! Do regular movement maintenance. + + This should be called pretty often, like once every 1 ot 2 milliseconds. + + Currently, this is checking the endstops. These don't need to be checked on + every single step, so this code can be moved out of the highly time critical + dda_step(). At high precision (slow) searches of the endstop, this function + is called more often than dda_step() anyways. + + In the future, acceleration and arc movement calculations might go here, too. + Updating speed 500 times a second is easily enough for smooth acceleration! +*/ +void dda_clock() { + DDA *dda; + static DDA *last_dda = NULL; + static uint8_t endstop_stop = 0; ///< Stop due to endstop trigger + + dda = queue_current_movement(); + if (dda != last_dda) { + move_state.debounce_count_xmin = move_state.debounce_count_ymin = + move_state.debounce_count_zmin = move_state.debounce_count_xmax = + move_state.debounce_count_ymax = move_state.debounce_count_zmax = 0; + endstop_stop = 0; + } + + if (dda == NULL) + return; + + // Caution: we mangle step counters here without locking interrupts. This + // means, we trust dda isn't changed behind our back, which could + // in principle (but rarely) happen if endstops are checked not as + // endstop search, but as part of normal operations. + if (endstop_stop == 0) { + #if defined X_MIN_PIN || defined X_MAX_PIN + if (dda->endstop_check & 0x1) { + #if defined X_MIN_PIN + if (x_min() == dda->endstop_stop_cond) + move_state.debounce_count_xmin++; + else + move_state.debounce_count_xmin = 0; + #endif + #if defined X_MAX_PIN + if (x_max() == dda->endstop_stop_cond) + move_state.debounce_count_xmax++; + else + move_state.debounce_count_xmax = 0; + #endif + endstop_stop = move_state.debounce_count_xmin >= ENDSTOP_STEPS || + move_state.debounce_count_xmax >= ENDSTOP_STEPS; + } + #endif + + #if defined Y_MIN_PIN || defined Y_MAX_PIN + if (dda->endstop_check & 0x2) { + #if defined Y_MIN_PIN + if (y_min() == dda->endstop_stop_cond) + move_state.debounce_count_ymin++; + else + move_state.debounce_count_ymin = 0; + #endif + #if defined Y_MAX_PIN + if (y_max() == dda->endstop_stop_cond) + move_state.debounce_count_ymax++; + else + move_state.debounce_count_ymax = 0; + #endif + endstop_stop = move_state.debounce_count_ymin >= ENDSTOP_STEPS || + move_state.debounce_count_ymax >= ENDSTOP_STEPS; + } + #endif + + #if defined Z_MIN_PIN || defined Z_MAX_PIN + if (dda->endstop_check & 0x4) { + #if defined Z_MIN_PIN + if (z_min() == dda->endstop_stop_cond) + move_state.debounce_count_zmin++; + else + move_state.debounce_count_zmin = 0; + #endif + #if defined Z_MAX_PIN + if (z_max() == dda->endstop_stop_cond) + move_state.debounce_count_zmax++; + else + move_state.debounce_count_zmax = 0; + #endif + endstop_stop = move_state.debounce_count_zmin >= ENDSTOP_STEPS || + move_state.debounce_count_zmax >= ENDSTOP_STEPS; + } + #endif + + // If an endstop is definitely triggered, stop the movement. + if (endstop_stop) { + // For always smooth operations, don't halt apruptly, + // but start deceleration here. + ATOMIC_START + dda->rampdown_steps = move_state.step_no; + dda->rampup_steps = 0; // in case we're still accelerating + ATOMIC_END + + endstops_off(); + } + } /* if (endstop_stop == 0) */ + + last_dda = dda; +} + /// update global current_position struct void update_current_position() { DDA *dda = &movebuffer[mb_tail]; diff --git a/dda.h b/dda.h index 3c1cbe3..5bc4238 100644 --- a/dda.h +++ b/dda.h @@ -205,6 +205,9 @@ void dda_start(DDA *dda) __attribute__ ((hot)); // DDA takes one step (called from timer interrupt) void dda_step(DDA *dda) __attribute__ ((hot)); +// regular movement maintenance +void dda_clock(void); + // update current_position void update_current_position(void); diff --git a/dda_queue.c b/dda_queue.c index ac7d0a8..fca6975 100644 --- a/dda_queue.c +++ b/dda_queue.c @@ -56,6 +56,20 @@ uint8_t queue_empty() { return result; } +/// Return the current movement, or NULL, if there's no movement going on. +DDA *queue_current_movement() { + DDA* current; + + ATOMIC_START + current = &movebuffer[mb_tail]; + + if ( ! current->live || current->waitfor_temp || current->nullmove) + current = NULL; + ATOMIC_END + + return current; +} + // ------------------------------------------------------- // This is the one function called by the timer interrupt. // It calls a few other functions, though. diff --git a/dda_queue.h b/dda_queue.h index ebaa414..752cff4 100644 --- a/dda_queue.h +++ b/dda_queue.h @@ -22,6 +22,7 @@ extern DDA movebuffer[MOVEBUFFER_SIZE]; // queue status methods uint8_t queue_full(void); uint8_t queue_empty(void); +DDA *queue_current_movement(void); // take one step void queue_step(void); diff --git a/timer.c b/timer.c index f3a7f4a..db6f597 100644 --- a/timer.c +++ b/timer.c @@ -57,6 +57,8 @@ ISR(TIMER1_COMPB_vect) { /* clock stuff */ + dda_clock(); + clock_counter_10ms += TICK_TIME_MS; if (clock_counter_10ms >= 10) { clock_counter_10ms -= 10;