🐛 Fix AVR maths used by Stepper (#25338)

This commit is contained in:
tombrazier 2023-02-21 22:37:11 +00:00 committed by Scott Lahteine
parent 9d56b7f073
commit e65e38afaf
3 changed files with 24 additions and 22 deletions

View File

@ -27,13 +27,14 @@
// intRes = longIn1 * longIn2 >> 24 // intRes = longIn1 * longIn2 >> 24
// uses: // uses:
// A[tmp] to store 0 // r1, r0 for the result of mul.
// B[tmp] to store bits 16-23 of the 48bit result. The top bit is used to round the two byte result. // [tmp1] to store 0.
// note that the lower two bytes and the upper byte of the 48bit result are not calculated. // [tmp2] to store bits 16-23 of the 56 bit result. The top bit of [tmp2] is used for rounding.
// this can cause the result to be out by one as the lower bytes may cause carries into the upper ones. // Note that the lower two bytes and the upper two bytes of the 56 bit result are not calculated.
// B A are bits 24-39 and are the returned value // This can cause the result to be out by one as the lower bytes may cause carries into the upper ones.
// C B A is longIn1 // [intRes] (A B) is bits 24-39 and is the returned value.
// D C B A is longIn2 // [longIn1] (C B A) is a 24 bit parameter.
// [longIn2] (D C B A) is a 32 bit parameter.
// //
FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) { FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
uint8_t tmp1; uint8_t tmp1;
@ -66,11 +67,9 @@ FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
A("add %[tmp2], r1") A("add %[tmp2], r1")
A("adc %A[intRes], %[tmp1]") A("adc %A[intRes], %[tmp1]")
A("adc %B[intRes], %[tmp1]") A("adc %B[intRes], %[tmp1]")
A("lsr %[tmp2]")
A("adc %A[intRes], %[tmp1]")
A("adc %B[intRes], %[tmp1]")
A("mul %D[longIn2], %A[longIn1]") A("mul %D[longIn2], %A[longIn1]")
A("add %A[intRes], r0") A("lsl %[tmp2]")
A("adc %A[intRes], r0")
A("adc %B[intRes], r1") A("adc %B[intRes], r1")
A("mul %D[longIn2], %B[longIn1]") A("mul %D[longIn2], %B[longIn1]")
A("add %B[intRes], r0") A("add %B[intRes], r0")
@ -85,11 +84,16 @@ FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
return intRes; return intRes;
} }
// intRes = intIn1 * intIn2 >> 16 // intRes = intIn1 * intIn2 >> 8
// uses: // uses:
// r26 to store 0 // r1, r0 for the result of mul. After the second mul, r0 holds bits 0-7 of the 24 bit result and
// r27 to store the byte 1 of the 24 bit result // the top bit of r0 is used for rounding.
FORCE_INLINE static uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) { // [tmp] to store 0.
// [intRes] (A B) is bits 8-15 and is the returned value.
// [charIn1] is an 8 bit parameter.
// [intIn2] (B A) is a 16 bit parameter.
//
FORCE_INLINE static uint16_t MultiU8X16toH16(uint8_t charIn1, uint16_t intIn2) {
uint8_t tmp; uint8_t tmp;
uint16_t intRes; uint16_t intRes;
__asm__ __volatile__ ( __asm__ __volatile__ (
@ -97,10 +101,8 @@ FORCE_INLINE static uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
A("mul %[charIn1], %B[intIn2]") A("mul %[charIn1], %B[intIn2]")
A("movw %A[intRes], r0") A("movw %A[intRes], r0")
A("mul %[charIn1], %A[intIn2]") A("mul %[charIn1], %A[intIn2]")
A("add %A[intRes], r1") A("lsl r0")
A("adc %B[intRes], %[tmp]") A("adc %A[intRes], r1")
A("lsr r0")
A("adc %A[intRes], %[tmp]")
A("adc %B[intRes], %[tmp]") A("adc %B[intRes], %[tmp]")
A("clr r1") A("clr r1")
: [intRes] "=&r" (intRes), : [intRes] "=&r" (intRes),

View File

@ -2062,7 +2062,7 @@ uint32_t Stepper::calc_timer_interval(uint32_t step_rate) {
const uint8_t rate_mod_256 = (step_rate & 0x00FF); const uint8_t rate_mod_256 = (step_rate & 0x00FF);
const uintptr_t table_address = uintptr_t(&speed_lookuptable_fast[uint8_t(step_rate >> 8)][0]), const uintptr_t table_address = uintptr_t(&speed_lookuptable_fast[uint8_t(step_rate >> 8)][0]),
gain = uint16_t(pgm_read_word(table_address + 2)); gain = uint16_t(pgm_read_word(table_address + 2));
return uint16_t(pgm_read_word(table_address)) - MultiU16X8toH16(rate_mod_256, gain); return uint16_t(pgm_read_word(table_address)) - MultiU8X16toH16(rate_mod_256, gain);
} }
else { // lower step rates else { // lower step rates
uintptr_t table_address = uintptr_t(&speed_lookuptable_slow[0][0]); uintptr_t table_address = uintptr_t(&speed_lookuptable_slow[0][0]);

View File

@ -114,11 +114,11 @@
#define TIMER_READ_ADD_AND_STORE_CYCLES 13UL #define TIMER_READ_ADD_AND_STORE_CYCLES 13UL
// The base ISR // The base ISR
#define ISR_BASE_CYCLES 1000UL #define ISR_BASE_CYCLES 996UL
// Linear advance base time is 32 cycles // Linear advance base time is 32 cycles
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
#define ISR_LA_BASE_CYCLES 32UL #define ISR_LA_BASE_CYCLES 30UL
#else #else
#define ISR_LA_BASE_CYCLES 0UL #define ISR_LA_BASE_CYCLES 0UL
#endif #endif