From 35926224145bd3217de6381676b15aaea584ea0f Mon Sep 17 00:00:00 2001 From: Nico Tonnhofer Date: Mon, 3 Apr 2017 22:55:26 +0200 Subject: [PATCH] dda.h/.c: remove move_state.step_no We don't need to save the step_no. We can easily calculate it when needed. Also some whitespace-work. In dda.h is only a delete of 'uint32_t step_no;'. Saves up to 16 clock cycles in dda_step(): short-moves.gcode statistics: LED on occurences: 888. LED on time minimum: 209 clock cycles. LED on time maximum: 504 clock cycles. LED on time average: 241.441 clock cycles. smooth-curves.gcode statistics: LED on occurences: 22589. LED on time minimum: 209 clock cycles. LED on time maximum: 521 clock cycles. LED on time average: 276.729 clock cycles. triangle-odd.gcode statistics: LED on occurences: 1636. LED on time minimum: 209 clock cycles. LED on time maximum: 504 clock cycles. LED on time average: 262.923 clock cycles. --- dda.c | 39 ++++++++++------------- dda.h | 101 ++++++++++++++++++++++++++++------------------------------ 2 files changed, 66 insertions(+), 74 deletions(-) diff --git a/dda.c b/dda.c index 14aed0b..e026c1e 100644 --- a/dda.c +++ b/dda.c @@ -507,9 +507,6 @@ void dda_start(DDA *dda) { move_state.counter[E] = -(dda->total_steps >> 1); move_state.endstop_stop = 0; memcpy(&move_state.steps[X], &dda->delta[X], sizeof(uint32_t) * 4); - #ifdef ACCELERATION_RAMPING - move_state.step_no = 0; - #endif #ifdef ACCELERATION_TEMPORAL move_state.time[X] = move_state.time[Y] = \ move_state.time[Z] = move_state.time[E] = 0UL; @@ -552,7 +549,7 @@ void dda_step(DDA *dda) { x_step(); move_state.steps[X]--; } - } + } if (move_state.steps[Y]) { move_state.counter[Y] -= dda->delta[Y]; if (move_state.counter[Y] < 0) { @@ -560,7 +557,7 @@ void dda_step(DDA *dda) { y_step(); move_state.steps[Y]--; } - } + } if (move_state.steps[Z]) { move_state.counter[Z] -= dda->delta[Z]; if (move_state.counter[Z] < 0) { @@ -568,7 +565,7 @@ void dda_step(DDA *dda) { z_step(); move_state.steps[Z]--; } - } + } if (move_state.steps[E]) { move_state.counter[E] -= dda->delta[E]; if (move_state.counter[E] < 0) { @@ -576,8 +573,7 @@ void dda_step(DDA *dda) { e_step(); move_state.steps[E]--; } - } - move_state.step_no++; + } #endif #ifdef ACCELERATION_REPRAP @@ -687,7 +683,7 @@ void dda_step(DDA *dda) { // TODO: with ACCELERATION_TEMPORAL this duplicates some code. See where // dda->live is zero'd, about 10 lines above. #if ! defined ACCELERATION_TEMPORAL - if (move_state.step_no >= dda->total_steps || + if (move_state.steps[dda->fast_axis] == 0 || (move_state.endstop_stop && dda->n <= 0)) #else if (move_state.steps[X] == 0 && move_state.steps[Y] == 0 && @@ -831,14 +827,16 @@ void dda_clock() { // For always smooth operations, don't halt apruptly, // but start deceleration here. ATOMIC_START + move_step_no = dda->total_steps - move_state.steps[dda->fast_axis]; + move_state.endstop_stop = 1; - if (move_state.step_no < dda->rampup_steps) // still accelerating - dda->total_steps = move_state.step_no * 2; + if (move_step_no < dda->rampup_steps) // still accelerating + dda->total_steps = move_step_no * 2; else // A "-=" would overflow earlier. dda->total_steps = dda->total_steps - dda->rampdown_steps + - move_state.step_no; - dda->rampdown_steps = move_state.step_no; + move_step_no; + dda->rampdown_steps = move_step_no; ATOMIC_END // Not atomic, because not used in dda_step(). dda->rampup_steps = 0; // in case we're still accelerating @@ -856,7 +854,7 @@ void dda_clock() { // and http://www.atmel.com/images/doc8017.pdf (Atmel app note AVR446) ATOMIC_START current_id = dda->id; - move_step_no = move_state.step_no; + move_step_no = dda->total_steps - move_state.steps[dda->fast_axis]; // All other variables are read-only or unused in dda_step(), // so no need for atomic operations. ATOMIC_END @@ -951,16 +949,13 @@ void update_current_position() { }; if (dda != NULL) { - uint32_t axis_steps, axis_um; + uint32_t axis_um; for (i = X; i < AXIS_COUNT; i++) { - #if ! defined ACCELERATION_TEMPORAL - axis_steps = muldiv(dda->total_steps - move_state.step_no, - dda->delta[i], dda->total_steps); - #else - axis_steps = move_state.steps[i]; - #endif - axis_um = muldiv(axis_steps, 1000000, pgm_read_dword(&steps_per_m_P[i])); + axis_um = muldiv(move_state.steps[i], + 1000000, + pgm_read_dword(&steps_per_m_P[i])); + current_position.axis[i] = dda->endpoint.axis[i] - (int32_t)get_direction(dda, i) * axis_um; } diff --git a/dda.h b/dda.h index 0c2f830..edb67a6 100644 --- a/dda.h +++ b/dda.h @@ -53,78 +53,75 @@ typedef struct { Parts of this struct are initialised only once per reboot, so make sure dda_step() leaves them with a value compatible to begin a new movement at the end of the movement. Other parts are filled in by dda_start(). */ typedef struct { - // bresenham counters - axes_int32_t counter; ///< counter for total_steps vs each axis + // bresenham counters + axes_int32_t counter; ///< counter for total_steps vs each axis - #if ! defined ACCELERATION_TEMPORAL - /// counts actual steps done - uint32_t step_no; - #else + #ifdef ACCELERATION_TEMPORAL axes_uint32_t time; ///< time of the last step on each axis uint32_t last_time; ///< time of the last step of any axis - #endif + #endif - axes_uint32_t steps; ///< number of steps on each axis - /// Endstop handling. - uint8_t endstop_stop; ///< Stop due to endstop trigger + axes_uint32_t steps; ///< number of steps on each axis + /// Endstop handling. + uint8_t endstop_stop; ///< Stop due to endstop trigger uint8_t debounce_count_x, debounce_count_y, debounce_count_z; } MOVE_STATE; /** - \struct DDA - \brief this is a digital differential analyser data struct + \struct DDA + \brief this is a digital differential analyser data struct - This struct holds all the details of an individual multi-axis move, including pre-calculated acceleration data. - This struct is filled in by dda_create(), called from enqueue(), called mostly from gcode_process() and from a few other places too (eg \file homing.c) + This struct holds all the details of an individual multi-axis move, including pre-calculated acceleration data. + This struct is filled in by dda_create(), called from enqueue(), called mostly from gcode_process() and from a few other places too (eg \file homing.c) */ typedef struct { - /// this is where we should finish - TARGET endpoint; + /// this is where we should finish + TARGET endpoint; - union { - struct { - // status fields - uint8_t nullmove :1; ///< bool: no axes move, maybe we wait for temperatures or change speed - volatile uint8_t live :1; ///< bool: this DDA is running and still has steps to do + union { + struct { + // status fields + uint8_t nullmove :1; ///< bool: no axes move, maybe we wait for temperatures or change speed + volatile uint8_t live :1; ///< bool: this DDA is running and still has steps to do uint8_t done :1; ///< bool: this DDA is done. - #ifdef ACCELERATION_REPRAP - uint8_t accel :1; ///< bool: speed changes during this move, run accel code - #endif + #ifdef ACCELERATION_REPRAP + uint8_t accel :1; ///< bool: speed changes during this move, run accel code + #endif - // directions + // directions // As we have muldiv() now, overflows became much less an issue and // it's likely time to get rid of these flags and use int instead of // uint for distance/speed calculations. --Traumflug 2014-07-04 - uint8_t x_direction :1; ///< direction flag for X axis - uint8_t y_direction :1; ///< direction flag for Y axis - uint8_t z_direction :1; ///< direction flag for Z axis - uint8_t e_direction :1; ///< direction flag for E axis - }; + uint8_t x_direction :1; ///< direction flag for X axis + uint8_t y_direction :1; ///< direction flag for Y axis + uint8_t z_direction :1; ///< direction flag for Z axis + uint8_t e_direction :1; ///< direction flag for E axis + }; uint16_t allflags; ///< used for clearing all flags - }; + }; - // distances + // distances axes_uint32_t delta; ///< number of steps on each axis // uint8_t fast_axis; (see below) uint32_t total_steps; ///< steps of the "fast" axis uint32_t fast_um; ///< movement length of this fast axis - uint32_t c; ///< time until next step, 24.8 fixed point + uint32_t c; ///< time until next step, 24.8 fixed point - #ifdef ACCELERATION_REPRAP - uint32_t end_c; ///< time between 2nd last step and last step - int32_t n; ///< precalculated step time offset variable - #endif - #ifdef ACCELERATION_RAMPING + #ifdef ACCELERATION_REPRAP + uint32_t end_c; ///< time between 2nd last step and last step + int32_t n; ///< precalculated step time offset variable + #endif + #ifdef ACCELERATION_RAMPING /// precalculated step time offset variable int32_t n; - /// number of steps accelerating - uint32_t rampup_steps; - /// number of last step before decelerating - uint32_t rampdown_steps; - /// 24.8 fixed point timer value, maximum speed - uint32_t c_min; + /// number of steps accelerating + uint32_t rampup_steps; + /// number of last step before decelerating + uint32_t rampdown_steps; + /// 24.8 fixed point timer value, maximum speed + uint32_t c_min; #ifdef LOOKAHEAD // With the look-ahead functionality, it is possible to retain physical // movement between G1 moves. These variables keep track of the entry and @@ -139,11 +136,11 @@ typedef struct { // are the same. Note: we do not need a lot of granularity here: more than // MOVEBUFFER_SIZE is already enough. uint8_t id; - #endif - #ifdef ACCELERATION_TEMPORAL + #endif + #ifdef ACCELERATION_TEMPORAL axes_uint32_t step_interval; ///< time between steps on each axis - uint8_t axis_to_step; ///< axis to be stepped on the next interrupt - #endif + uint8_t axis_to_step; ///< axis to be stepped on the next interrupt + #endif /// Small variables. Many CPUs can access 32-bit variables at word or double /// word boundaries only and fill smaller variables in between with gaps, @@ -151,13 +148,13 @@ typedef struct { /// gaps. See e.g. NXP application note AN10963, page 10f. uint8_t fast_axis; ///< number of the fast axis - /// Endstop homing - uint8_t endstop_check; ///< Do we need to check endstops? 0x1=Check X, 0x2=Check Y, 0x4=Check Z - uint8_t endstop_stop_cond; ///< Endstop condition on which to stop motion: 0=Stop on detrigger, 1=Stop on trigger + /// Endstop homing + uint8_t endstop_check; ///< Do we need to check endstops? 0x1=Check X, 0x2=Check Y, 0x4=Check Z + uint8_t endstop_stop_cond; ///< Endstop condition on which to stop motion: 0=Stop on detrigger, 1=Stop on trigger } DDA; /* - variables + variables */ /// startpoint holds the endpoint of the most recently created DDA, so we know where the next one created starts. could also be called last_endpoint