Use the new muldiv() to replace um_to_steps..().

This gets rid of overflows at micrometer to step conversion as
much as possible within 31 bits. It also opens the door to get
STEPS_PER_M configurable at runtime.

This also costs 290 bytes, unfortunately.
This commit is contained in:
Markus Hitter 2012-04-24 03:30:57 +02:00
parent 9359350fcc
commit 0068ed1e26
3 changed files with 17 additions and 84 deletions

19
dda.c
View File

@ -9,6 +9,7 @@
#include <math.h>
#include <avr/interrupt.h>
#include "dda_maths.h"
#include "timer.h"
#include "serial.h"
#include "sermsg.h"
@ -188,10 +189,10 @@ void dda_init(void) {
This is needed for example after homing or a G92. The new location must be in startpoint already.
*/
void dda_new_startpoint(void) {
um_to_steps_x(startpoint_steps.X, startpoint.X);
um_to_steps_y(startpoint_steps.Y, startpoint.Y);
um_to_steps_z(startpoint_steps.Z, startpoint.Z);
um_to_steps_e(startpoint_steps.E, startpoint.E);
startpoint_steps.X = um_to_steps_x(startpoint.X);
startpoint_steps.Y = um_to_steps_y(startpoint.Y);
startpoint_steps.Z = um_to_steps_z(startpoint.Z);
startpoint_steps.E = um_to_steps_e(startpoint.E);
}
/*! CREATE a dda given current_position and a target, save to passed location so we can write directly into the queue
@ -226,13 +227,13 @@ void dda_create(DDA *dda, TARGET *target) {
y_delta_um = (uint32_t)labs(target->Y - startpoint.Y);
z_delta_um = (uint32_t)labs(target->Z - startpoint.Z);
um_to_steps_x(steps, target->X);
steps = um_to_steps_x(target->X);
dda->x_delta = labs(steps - startpoint_steps.X);
startpoint_steps.X = steps;
um_to_steps_y(steps, target->Y);
steps = um_to_steps_y(target->Y);
dda->y_delta = labs(steps - startpoint_steps.Y);
startpoint_steps.Y = steps;
um_to_steps_z(steps, target->Z);
steps = um_to_steps_z(target->Z);
dda->z_delta = labs(steps - startpoint_steps.Z);
startpoint_steps.Z = steps;
@ -242,12 +243,12 @@ void dda_create(DDA *dda, TARGET *target) {
if (target->e_relative) {
e_delta_um = labs(target->E);
um_to_steps_e(dda->e_delta, e_delta_um);
dda->e_delta = um_to_steps_e(target->E);
dda->e_direction = (target->E >= 0)?1:0;
}
else {
e_delta_um = (uint32_t)labs(target->E - startpoint.E);
um_to_steps_e(steps, target->E);
steps = um_to_steps_e(target->E);
dda->e_delta = labs(steps - startpoint_steps.E);
startpoint_steps.E = steps;
dda->e_direction = (target->E >= startpoint.E)?1:0;

75
dda.h
View File

@ -5,81 +5,6 @@
#include "config.h"
/*
micrometer to steps conversion
handle a few cases to avoid overflow while keeping reasonable accuracy
input is up to 20 bits, so we can multiply by 4096 at most
*/
#if STEPS_PER_M_X >= 4096000
#define um_to_steps_x(dest, src) \
do { dest = (src * (STEPS_PER_M_X / 10000L) + 50L) / 100L; } while (0)
#elif STEPS_PER_M_X >= 409600
#define um_to_steps_x(dest, src) \
do { dest = (src * (STEPS_PER_M_X / 1000L) + 500L) / 1000L; } while (0)
#elif STEPS_PER_M_X >= 40960
#define um_to_steps_x(dest, src) \
do { dest = (src * (STEPS_PER_M_X / 100L) + 5000L) / 10000L; } while (0)
#elif STEPS_PER_M_X >= 4096
#define um_to_steps_x(dest, src) \
do { dest = (src * (STEPS_PER_M_X / 10L) + 50000L) / 100000L; } while (0)
#else
#define um_to_steps_x(dest, src) \
do { dest = (src * (STEPS_PER_M_X / 1L) + 500000L) / 1000000L; } while (0)
#endif
#if STEPS_PER_M_Y >= 4096000
#define um_to_steps_y(dest, src) \
do { dest = (src * (STEPS_PER_M_Y / 10000L) + 50L) / 100L; } while (0)
#elif STEPS_PER_M_Y >= 409600
#define um_to_steps_y(dest, src) \
do { dest = (src * (STEPS_PER_M_Y / 1000L) + 500L) / 1000L; } while (0)
#elif STEPS_PER_M_Y >= 40960
#define um_to_steps_y(dest, src) \
do { dest = (src * (STEPS_PER_M_Y / 100L) + 5000L) / 10000L; } while (0)
#elif STEPS_PER_M_Y >= 4096
#define um_to_steps_y(dest, src) \
do { dest = (src * (STEPS_PER_M_Y / 10L) + 50000L) / 100000L; } while (0)
#else
#define um_to_steps_y(dest, src) \
do { dest = (src * (STEPS_PER_M_Y / 1L) + 500000L) / 1000000L; } while (0)
#endif
#if STEPS_PER_M_Z >= 4096000
#define um_to_steps_z(dest, src) \
do { dest = (src * (STEPS_PER_M_Z / 10000L) + 50L) / 100L; } while (0)
#elif STEPS_PER_M_Z >= 409600
#define um_to_steps_z(dest, src) \
do { dest = (src * (STEPS_PER_M_Z / 1000L) + 500L) / 1000L; } while (0)
#elif STEPS_PER_M_Z >= 40960
#define um_to_steps_z(dest, src) \
do { dest = (src * (STEPS_PER_M_Z / 100L) + 5000L) / 10000L; } while (0)
#elif STEPS_PER_M_Z >= 4096
#define um_to_steps_z(dest, src) \
do { dest = (src * (STEPS_PER_M_Z / 10L) + 50000L) / 100000L; } while (0)
#else
#define um_to_steps_z(dest, src) \
do { dest = (src * (STEPS_PER_M_Z / 1L) + 500000L) / 1000000L; } while (0)
#endif
#if STEPS_PER_M_E >= 4096000
#define um_to_steps_e(dest, src) \
do { dest = (src * (STEPS_PER_M_E / 10000L) + 50L) / 100L; } while (0)
#elif STEPS_PER_M_E >= 409600
#define um_to_steps_e(dest, src) \
do { dest = (src * (STEPS_PER_M_E / 1000L) + 500L) / 1000L; } while (0)
#elif STEPS_PER_M_E >= 40960
#define um_to_steps_e(dest, src) \
do { dest = (src * (STEPS_PER_M_E / 100L) + 5000L) / 10000L; } while (0)
#elif STEPS_PER_M_E >= 4096
#define um_to_steps_e(dest, src) \
do { dest = (src * (STEPS_PER_M_E / 10L) + 50000L) / 100000L; } while (0)
#else
#define um_to_steps_e(dest, src) \
do { dest = (src * (STEPS_PER_M_E / 1L) + 500000L) / 1000000L; } while (0)
#endif
#ifdef ACCELERATION_REPRAP
#ifdef ACCELERATION_RAMPING
#error Cant use ACCELERATION_REPRAP and ACCELERATION_RAMPING together.

View File

@ -3,9 +3,16 @@
#include <stdint.h>
#include "config.h"
// return rounded result of multiplicand * multiplier / divisor
const int32_t muldiv(int32_t multiplicand, uint32_t multiplier,
uint32_t divisor);
// convert micrometer distances to motor step distances
#define um_to_steps_x(distance) muldiv(distance, STEPS_PER_M_X, 1000000UL);
#define um_to_steps_y(distance) muldiv(distance, STEPS_PER_M_Y, 1000000UL);
#define um_to_steps_z(distance) muldiv(distance, STEPS_PER_M_Z, 1000000UL);
#define um_to_steps_e(distance) muldiv(distance, STEPS_PER_M_E, 1000000UL);
#endif /* _DDA_MATHS_H */