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.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;
}

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().
*/
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