From 62bdbd86d6eeec59d00274c8d10194919f3f7a7a Mon Sep 17 00:00:00 2001 From: Phil Hord Date: Tue, 19 Nov 2013 17:41:56 -0500 Subject: [PATCH] DDA: convert um_to_steps_* to generic implementation. A generic implementation here will allow callers to pass the target axis in as a parameter so the callers can also be made more generic. Traumflug notes: Split out application of the new implementation in dda.c into its own commit. This actually costs 128 bytes, but as we can access axes from within a loop now, I expect to get more savings elsewhere. Interestingly, binary size is raised by another 18 bytes if um_to_steps(int32_t, enum axis_e) is changed to um_to_steps(enum axis_e, int32_t) even on the 8-bit ATmega. While putting the axis number to the front might be a bit more logical (think of additional parameters, the axis number position would move), NXP application note AN10963 states on page 10ff, 16-bit data should be 16-bit aligned and 32-bit data should be 32-bit aligned for best performance. Well, so let's do it this way. --- dda.h | 6 ++++++ dda_maths.c | 20 ++++++++++++++++++++ dda_maths.h | 32 ++++++++++++++++++-------------- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/dda.h b/dda.h index ce7b3c5..8f04aab 100644 --- a/dda.h +++ b/dda.h @@ -11,6 +11,12 @@ #endif #endif +#ifndef SIMULATOR + #include +#else + #define PROGMEM +#endif + /* types */ diff --git a/dda_maths.c b/dda_maths.c index 908ce59..8294dda 100644 --- a/dda_maths.c +++ b/dda_maths.c @@ -8,6 +8,26 @@ #include #include +/*! + Pre-calculated constant values for axis um <=> steps conversions. + + These should be calculated at run-time once in dda_init() if the + STEPS_PER_M_* constants are ever replaced with run-time options. +*/ +const axes_uint32_t PROGMEM axis_qn = { + (uint32_t)STEPS_PER_M_X / UM_PER_METER, + (uint32_t)STEPS_PER_M_Y / UM_PER_METER, + (uint32_t)STEPS_PER_M_Z / UM_PER_METER, + (uint32_t)STEPS_PER_M_E / UM_PER_METER +}; + +const axes_uint32_t PROGMEM axis_qr = { + (uint32_t)STEPS_PER_M_X % UM_PER_METER, + (uint32_t)STEPS_PER_M_Y % UM_PER_METER, + (uint32_t)STEPS_PER_M_Z % UM_PER_METER, + (uint32_t)STEPS_PER_M_E % UM_PER_METER +}; + /*! Integer multiply-divide algorithm. Returns the same as muldiv(multiplicand, multiplier, divisor), but also allowing to use precalculated quotients and remainders. diff --git a/dda_maths.h b/dda_maths.h index 0f25bf7..19dda08 100644 --- a/dda_maths.h +++ b/dda_maths.h @@ -4,6 +4,7 @@ #include #include "config_wrapper.h" +#include "dda.h" // return rounded result of multiplicand * multiplier / divisor // this version is with quotient and remainder precalculated elsewhere @@ -18,36 +19,39 @@ inline int32_t muldiv(int32_t multiplicand, uint32_t multiplier, multiplier % divisor, divisor); } -/* - micrometer distance <=> motor step distance conversions +/*! + Micrometer distance <=> motor step distance conversions. */ -// Like shown in the patch attached to this post: -// http://forums.reprap.org/read.php?147,89710,130225#msg-130225 , -// it might be worth pre-calculating muldivQR()'s qn and rn in dda_init() -// as soon as STEPS_PER_M_{XYZE} is no longer a compile-time variable. + +#define UM_PER_METER (1000000UL) + +extern const axes_uint32_t PROGMEM axis_qn; +extern const axes_uint32_t PROGMEM axis_qr; + +static int32_t um_to_steps(int32_t, enum axis_e) __attribute__ ((always_inline)); +inline int32_t um_to_steps(int32_t distance, enum axis_e a) { + return muldivQR(distance, pgm_read_dword(&axis_qn[a]), + pgm_read_dword(&axis_qr[a]), UM_PER_METER); +} static int32_t um_to_steps_x(int32_t) __attribute__ ((always_inline)); inline int32_t um_to_steps_x(int32_t distance) { - return muldivQR(distance, STEPS_PER_M_X / 1000000UL, - STEPS_PER_M_X % 1000000UL, 1000000UL); + return um_to_steps(distance, X); } static int32_t um_to_steps_y(int32_t) __attribute__ ((always_inline)); inline int32_t um_to_steps_y(int32_t distance) { - return muldivQR(distance, STEPS_PER_M_Y / 1000000UL, - STEPS_PER_M_Y % 1000000UL, 1000000UL); + return um_to_steps(distance, Y); } static int32_t um_to_steps_z(int32_t) __attribute__ ((always_inline)); inline int32_t um_to_steps_z(int32_t distance) { - return muldivQR(distance, STEPS_PER_M_Z / 1000000UL, - STEPS_PER_M_Z % 1000000UL, 1000000UL); + return um_to_steps(distance, Z); } static int32_t um_to_steps_e(int32_t) __attribute__ ((always_inline)); inline int32_t um_to_steps_e(int32_t distance) { - return muldivQR(distance, STEPS_PER_M_E / 1000000UL, - STEPS_PER_M_E % 1000000UL, 1000000UL); + return um_to_steps(distance, E); } // approximate 2D distance