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.
This commit is contained in:
Nico Tonnhofer 2017-04-03 22:55:26 +02:00
parent 89bb0ae3bb
commit 3592622414
2 changed files with 66 additions and 74 deletions

39
dda.c
View File

@ -507,9 +507,6 @@ void dda_start(DDA *dda) {
move_state.counter[E] = -(dda->total_steps >> 1); move_state.counter[E] = -(dda->total_steps >> 1);
move_state.endstop_stop = 0; move_state.endstop_stop = 0;
memcpy(&move_state.steps[X], &dda->delta[X], sizeof(uint32_t) * 4); memcpy(&move_state.steps[X], &dda->delta[X], sizeof(uint32_t) * 4);
#ifdef ACCELERATION_RAMPING
move_state.step_no = 0;
#endif
#ifdef ACCELERATION_TEMPORAL #ifdef ACCELERATION_TEMPORAL
move_state.time[X] = move_state.time[Y] = \ move_state.time[X] = move_state.time[Y] = \
move_state.time[Z] = move_state.time[E] = 0UL; move_state.time[Z] = move_state.time[E] = 0UL;
@ -552,7 +549,7 @@ void dda_step(DDA *dda) {
x_step(); x_step();
move_state.steps[X]--; move_state.steps[X]--;
} }
} }
if (move_state.steps[Y]) { if (move_state.steps[Y]) {
move_state.counter[Y] -= dda->delta[Y]; move_state.counter[Y] -= dda->delta[Y];
if (move_state.counter[Y] < 0) { if (move_state.counter[Y] < 0) {
@ -560,7 +557,7 @@ void dda_step(DDA *dda) {
y_step(); y_step();
move_state.steps[Y]--; move_state.steps[Y]--;
} }
} }
if (move_state.steps[Z]) { if (move_state.steps[Z]) {
move_state.counter[Z] -= dda->delta[Z]; move_state.counter[Z] -= dda->delta[Z];
if (move_state.counter[Z] < 0) { if (move_state.counter[Z] < 0) {
@ -568,7 +565,7 @@ void dda_step(DDA *dda) {
z_step(); z_step();
move_state.steps[Z]--; move_state.steps[Z]--;
} }
} }
if (move_state.steps[E]) { if (move_state.steps[E]) {
move_state.counter[E] -= dda->delta[E]; move_state.counter[E] -= dda->delta[E];
if (move_state.counter[E] < 0) { if (move_state.counter[E] < 0) {
@ -576,8 +573,7 @@ void dda_step(DDA *dda) {
e_step(); e_step();
move_state.steps[E]--; move_state.steps[E]--;
} }
} }
move_state.step_no++;
#endif #endif
#ifdef ACCELERATION_REPRAP #ifdef ACCELERATION_REPRAP
@ -687,7 +683,7 @@ void dda_step(DDA *dda) {
// TODO: with ACCELERATION_TEMPORAL this duplicates some code. See where // TODO: with ACCELERATION_TEMPORAL this duplicates some code. See where
// dda->live is zero'd, about 10 lines above. // dda->live is zero'd, about 10 lines above.
#if ! defined ACCELERATION_TEMPORAL #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)) (move_state.endstop_stop && dda->n <= 0))
#else #else
if (move_state.steps[X] == 0 && move_state.steps[Y] == 0 && 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, // For always smooth operations, don't halt apruptly,
// but start deceleration here. // but start deceleration here.
ATOMIC_START ATOMIC_START
move_step_no = dda->total_steps - move_state.steps[dda->fast_axis];
move_state.endstop_stop = 1; move_state.endstop_stop = 1;
if (move_state.step_no < dda->rampup_steps) // still accelerating if (move_step_no < dda->rampup_steps) // still accelerating
dda->total_steps = move_state.step_no * 2; dda->total_steps = move_step_no * 2;
else else
// A "-=" would overflow earlier. // A "-=" would overflow earlier.
dda->total_steps = dda->total_steps - dda->rampdown_steps + dda->total_steps = dda->total_steps - dda->rampdown_steps +
move_state.step_no; move_step_no;
dda->rampdown_steps = move_state.step_no; dda->rampdown_steps = move_step_no;
ATOMIC_END ATOMIC_END
// Not atomic, because not used in dda_step(). // Not atomic, because not used in dda_step().
dda->rampup_steps = 0; // in case we're still accelerating 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) // and http://www.atmel.com/images/doc8017.pdf (Atmel app note AVR446)
ATOMIC_START ATOMIC_START
current_id = dda->id; 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(), // All other variables are read-only or unused in dda_step(),
// so no need for atomic operations. // so no need for atomic operations.
ATOMIC_END ATOMIC_END
@ -951,16 +949,13 @@ void update_current_position() {
}; };
if (dda != NULL) { if (dda != NULL) {
uint32_t axis_steps, axis_um; uint32_t axis_um;
for (i = X; i < AXIS_COUNT; i++) { for (i = X; i < AXIS_COUNT; i++) {
#if ! defined ACCELERATION_TEMPORAL axis_um = muldiv(move_state.steps[i],
axis_steps = muldiv(dda->total_steps - move_state.step_no, 1000000,
dda->delta[i], dda->total_steps); pgm_read_dword(&steps_per_m_P[i]));
#else
axis_steps = move_state.steps[i];
#endif
axis_um = muldiv(axis_steps, 1000000, pgm_read_dword(&steps_per_m_P[i]));
current_position.axis[i] = current_position.axis[i] =
dda->endpoint.axis[i] - (int32_t)get_direction(dda, i) * axis_um; dda->endpoint.axis[i] - (int32_t)get_direction(dda, i) * axis_um;
} }

101
dda.h
View File

@ -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(). 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 { typedef struct {
// bresenham counters // bresenham counters
axes_int32_t counter; ///< counter for total_steps vs each axis axes_int32_t counter; ///< counter for total_steps vs each axis
#if ! defined ACCELERATION_TEMPORAL #ifdef ACCELERATION_TEMPORAL
/// counts actual steps done
uint32_t step_no;
#else
axes_uint32_t time; ///< time of the last step on each axis axes_uint32_t time; ///< time of the last step on each axis
uint32_t last_time; ///< time of the last step of any 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 axes_uint32_t steps; ///< number of steps on each axis
/// Endstop handling. /// Endstop handling.
uint8_t endstop_stop; ///< Stop due to endstop trigger uint8_t endstop_stop; ///< Stop due to endstop trigger
uint8_t debounce_count_x, debounce_count_y, debounce_count_z; uint8_t debounce_count_x, debounce_count_y, debounce_count_z;
} MOVE_STATE; } MOVE_STATE;
/** /**
\struct DDA \struct DDA
\brief this is a digital differential analyser data struct \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 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 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 { typedef struct {
/// this is where we should finish /// this is where we should finish
TARGET endpoint; TARGET endpoint;
union { union {
struct { struct {
// status fields // status fields
uint8_t nullmove :1; ///< bool: no axes move, maybe we wait for temperatures or change speed 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 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. uint8_t done :1; ///< bool: this DDA is done.
#ifdef ACCELERATION_REPRAP #ifdef ACCELERATION_REPRAP
uint8_t accel :1; ///< bool: speed changes during this move, run accel code uint8_t accel :1; ///< bool: speed changes during this move, run accel code
#endif #endif
// directions // directions
// As we have muldiv() now, overflows became much less an issue and // 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 // it's likely time to get rid of these flags and use int instead of
// uint for distance/speed calculations. --Traumflug 2014-07-04 // uint for distance/speed calculations. --Traumflug 2014-07-04
uint8_t x_direction :1; ///< direction flag for X axis uint8_t x_direction :1; ///< direction flag for X axis
uint8_t y_direction :1; ///< direction flag for Y axis uint8_t y_direction :1; ///< direction flag for Y axis
uint8_t z_direction :1; ///< direction flag for Z axis uint8_t z_direction :1; ///< direction flag for Z axis
uint8_t e_direction :1; ///< direction flag for E axis uint8_t e_direction :1; ///< direction flag for E axis
}; };
uint16_t allflags; ///< used for clearing all flags uint16_t allflags; ///< used for clearing all flags
}; };
// distances // distances
axes_uint32_t delta; ///< number of steps on each axis axes_uint32_t delta; ///< number of steps on each axis
// uint8_t fast_axis; (see below) // uint8_t fast_axis; (see below)
uint32_t total_steps; ///< steps of the "fast" axis uint32_t total_steps; ///< steps of the "fast" axis
uint32_t fast_um; ///< movement length of this 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 #ifdef ACCELERATION_REPRAP
uint32_t end_c; ///< time between 2nd last step and last step uint32_t end_c; ///< time between 2nd last step and last step
int32_t n; ///< precalculated step time offset variable int32_t n; ///< precalculated step time offset variable
#endif #endif
#ifdef ACCELERATION_RAMPING #ifdef ACCELERATION_RAMPING
/// precalculated step time offset variable /// precalculated step time offset variable
int32_t n; int32_t n;
/// number of steps accelerating /// number of steps accelerating
uint32_t rampup_steps; uint32_t rampup_steps;
/// number of last step before decelerating /// number of last step before decelerating
uint32_t rampdown_steps; uint32_t rampdown_steps;
/// 24.8 fixed point timer value, maximum speed /// 24.8 fixed point timer value, maximum speed
uint32_t c_min; uint32_t c_min;
#ifdef LOOKAHEAD #ifdef LOOKAHEAD
// With the look-ahead functionality, it is possible to retain physical // With the look-ahead functionality, it is possible to retain physical
// movement between G1 moves. These variables keep track of the entry and // 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 // are the same. Note: we do not need a lot of granularity here: more than
// MOVEBUFFER_SIZE is already enough. // MOVEBUFFER_SIZE is already enough.
uint8_t id; uint8_t id;
#endif #endif
#ifdef ACCELERATION_TEMPORAL #ifdef ACCELERATION_TEMPORAL
axes_uint32_t step_interval; ///< time between steps on each axis axes_uint32_t step_interval; ///< time between steps on each axis
uint8_t axis_to_step; ///< axis to be stepped on the next interrupt uint8_t axis_to_step; ///< axis to be stepped on the next interrupt
#endif #endif
/// Small variables. Many CPUs can access 32-bit variables at word or double /// Small variables. Many CPUs can access 32-bit variables at word or double
/// word boundaries only and fill smaller variables in between with gaps, /// 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. /// gaps. See e.g. NXP application note AN10963, page 10f.
uint8_t fast_axis; ///< number of the fast axis uint8_t fast_axis; ///< number of the fast axis
/// Endstop homing /// Endstop homing
uint8_t endstop_check; ///< Do we need to check endstops? 0x1=Check X, 0x2=Check Y, 0x4=Check Z 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 uint8_t endstop_stop_cond; ///< Endstop condition on which to stop motion: 0=Stop on detrigger, 1=Stop on trigger
} DDA; } 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 /// 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