diff --git a/Makefile b/Makefile index 5391157..d33ccf2 100644 --- a/Makefile +++ b/Makefile @@ -80,7 +80,7 @@ PROGID = arduino PROGRAM = mendel -SOURCES = $(PROGRAM).c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c intercom.c pinio.c clock.c home.c crc.c delay.c +SOURCES = $(PROGRAM).c gcode_parse.c gcode_process.c dda.c dda_maths.c dda_queue.c timer.c temp.c sermsg.c watchdog.c debug.c sersendf.c heater.c analog.c intercom.c pinio.c clock.c home.c crc.c delay.c ARCH = avr- CC = $(ARCH)gcc diff --git a/dda_maths.c b/dda_maths.c new file mode 100644 index 0000000..1c6d8db --- /dev/null +++ b/dda_maths.c @@ -0,0 +1,60 @@ + +/** \file + \brief Mathematic algorithms for the digital differential analyser (DDA). +*/ + +#include "dda_maths.h" + +#include +#include + +/*! + Integer multiply-divide algorithm. + + \param multiplicand + \param multiplier + \param divisor + \return rounded result of multiplicand * multiplier / divisor + + Calculate a * b / c, without overflowing and without using 64-bit integers. + Doing this the standard way, a * b could easily overflow, even if the correct + overall result fits into 32 bits. This algorithm avoids this intermediate + overflow and delivers valid results for all cases where each of the three + operators as well as the result fits into 32 bits. + + Found on http://stackoverflow.com/questions/4144232/ + how-to-calculate-a-times-b-divided-by-c-only-using-32-bit-integer-types-even-i +*/ +const uint32_t muldiv(uint32_t multiplicand, uint32_t multiplier, + uint32_t divisor) { + uint32_t quotient = 0; + uint32_t remainder = 0; + uint32_t qn = multiplier / divisor; + uint32_t rn = multiplier % divisor; + + while(multiplicand) { + if (multiplicand & 1) { + quotient += qn; + remainder += rn; + if (remainder >= divisor) { + quotient++; + remainder -= divisor; + } + } + multiplicand >>= 1; + qn <<= 1; + rn <<= 1; + if (rn >= divisor) { + qn++; + rn -= divisor; + } + } + + // rounding + if (remainder > divisor / 2) + quotient++; + + // remainder is valid here, but not returned + return quotient; +} + diff --git a/dda_maths.h b/dda_maths.h new file mode 100644 index 0000000..9efcf7a --- /dev/null +++ b/dda_maths.h @@ -0,0 +1,11 @@ +#ifndef _DDA_MATHS_H +#define _DDA_MATHS_H + +#include + + +// return rounded result of multiplicand * multiplier / divisor +const uint32_t muldiv(uint32_t multiplicand, uint32_t multiplier, + uint32_t divisor); + +#endif /* _DDA_MATHS_H */