Merge pull request #10651 from thinkyhead/bf2_junction_deviation

[2.0.x] Junction Deviation
This commit is contained in:
Scott Lahteine 2018-05-08 11:09:01 -05:00 committed by GitHub
commit 2cdaf76c40
Signed by: GitHub
GPG key ID: 4AEE18F83AFDEB23
60 changed files with 1451 additions and 967 deletions

View file

@ -84,7 +84,7 @@ script:
- opt_set TEMP_SENSOR_4 999
- opt_set TEMP_SENSOR_BED 1
- opt_enable AUTO_BED_LEVELING_UBL RESTORE_LEVELING_AFTER_G28 DEBUG_LEVELING_FEATURE G26_MESH_EDITING ENABLE_LEVELING_FADE_HEIGHT EEPROM_SETTINGS EEPROM_CHITCHAT G3D_PANEL SKEW_CORRECTION
- opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING BABYSTEP_XY LIN_ADVANCE NANODLP_Z_SYNC QUICK_HOME
- opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING BABYSTEP_XY LIN_ADVANCE NANODLP_Z_SYNC QUICK_HOME JUNCTION_DEVIATION
- build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
#
# Add a Sled Z Probe, use UBL Cartesian moves, use Japanese language

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -23,6 +23,8 @@
#ifndef _MATH_AVR_H_
#define _MATH_AVR_H_
#define a(CODE) " " CODE "\n\t"
/**
* Optimized math functions for AVR
*/
@ -39,41 +41,41 @@
//
#define MultiU24X32toH16(intRes, longIn1, longIn2) \
asm volatile ( \
"clr r26 \n\t" \
"mul %A1, %B2 \n\t" \
"mov r27, r1 \n\t" \
"mul %B1, %C2 \n\t" \
"movw %A0, r0 \n\t" \
"mul %C1, %C2 \n\t" \
"add %B0, r0 \n\t" \
"mul %C1, %B2 \n\t" \
"add %A0, r0 \n\t" \
"adc %B0, r1 \n\t" \
"mul %A1, %C2 \n\t" \
"add r27, r0 \n\t" \
"adc %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"mul %B1, %B2 \n\t" \
"add r27, r0 \n\t" \
"adc %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"mul %C1, %A2 \n\t" \
"add r27, r0 \n\t" \
"adc %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"mul %B1, %A2 \n\t" \
"add r27, r1 \n\t" \
"adc %A0, r26 \n\t" \
"adc %B0, r26 \n\t" \
"lsr r27 \n\t" \
"adc %A0, r26 \n\t" \
"adc %B0, r26 \n\t" \
"mul %D2, %A1 \n\t" \
"add %A0, r0 \n\t" \
"adc %B0, r1 \n\t" \
"mul %D2, %B1 \n\t" \
"add %B0, r0 \n\t" \
"clr r1 \n\t" \
A("clr r26") \
A("mul %A1, %B2") \
A("mov r27, r1") \
A("mul %B1, %C2") \
A("movw %A0, r0") \
A("mul %C1, %C2") \
A("add %B0, r0") \
A("mul %C1, %B2") \
A("add %A0, r0") \
A("adc %B0, r1") \
A("mul %A1, %C2") \
A("add r27, r0") \
A("adc %A0, r1") \
A("adc %B0, r26") \
A("mul %B1, %B2") \
A("add r27, r0") \
A("adc %A0, r1") \
A("adc %B0, r26") \
A("mul %C1, %A2") \
A("add r27, r0") \
A("adc %A0, r1") \
A("adc %B0, r26") \
A("mul %B1, %A2") \
A("add r27, r1") \
A("adc %A0, r26") \
A("adc %B0, r26") \
A("lsr r27") \
A("adc %A0, r26") \
A("adc %B0, r26") \
A("mul %D2, %A1") \
A("add %A0, r0") \
A("adc %B0, r1") \
A("mul %D2, %B1") \
A("add %B0, r0") \
A("clr r1") \
: \
"=&r" (intRes) \
: \
@ -89,16 +91,16 @@
// r27 to store the byte 1 of the 24 bit result
#define MultiU16X8toH16(intRes, charIn1, intIn2) \
asm volatile ( \
"clr r26 \n\t" \
"mul %A1, %B2 \n\t" \
"movw %A0, r0 \n\t" \
"mul %A1, %A2 \n\t" \
"add %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"lsr r0 \n\t" \
"adc %A0, r26 \n\t" \
"adc %B0, r26 \n\t" \
"clr r1 \n\t" \
A("clr r26") \
A("mul %A1, %B2") \
A("movw %A0, r0") \
A("mul %A1, %A2") \
A("add %A0, r1") \
A("adc %B0, r26") \
A("lsr r0") \
A("adc %A0, r26") \
A("adc %B0, r26") \
A("clr r1") \
: \
"=&r" (intRes) \
: \

View file

@ -36,7 +36,7 @@
// state we are when running them
// A SW memory barrier, to ensure GCC does not overoptimize loops
#define sw_barrier() asm volatile("": : :"memory");
#define sw_barrier() __asm__ volatile("": : :"memory");
// (re)initialize UART0 as a monitor output to 250000,n,8,1
static void TXBegin(void) {
@ -230,106 +230,106 @@ void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause
__attribute__((naked)) void NMI_Handler(void) {
__asm__ __volatile__ (
".syntax unified \n"
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" mov r1,lr \n"
" mov r2,#0 \n"
" b HardFault_HandlerC \n"
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#0")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void HardFault_Handler(void) {
__asm__ __volatile__ (
".syntax unified \n"
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" mov r1,lr \n"
" mov r2,#1 \n"
" b HardFault_HandlerC \n"
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#1")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void MemManage_Handler(void) {
__asm__ __volatile__ (
".syntax unified \n"
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" mov r1,lr \n"
" mov r2,#2 \n"
" b HardFault_HandlerC \n"
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#2")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void BusFault_Handler(void) {
__asm__ __volatile__ (
".syntax unified \n"
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" mov r1,lr \n"
" mov r2,#3 \n"
" b HardFault_HandlerC \n"
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#3")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void UsageFault_Handler(void) {
__asm__ __volatile__ (
".syntax unified \n"
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" mov r1,lr \n"
" mov r2,#4 \n"
" b HardFault_HandlerC \n"
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#4")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void DebugMon_Handler(void) {
__asm__ __volatile__ (
".syntax unified \n"
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" mov r1,lr \n"
" mov r2,#5 \n"
" b HardFault_HandlerC \n"
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#5")
A("b HardFault_HandlerC")
);
}
/* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
__attribute__((naked)) void WDT_Handler(void) {
__asm__ __volatile__ (
".syntax unified \n"
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" mov r1,lr \n"
" mov r2,#6 \n"
" b HardFault_HandlerC \n"
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#6")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void RSTC_Handler(void) {
__asm__ __volatile__ (
".syntax unified \n"
" tst lr, #4 \n"
" ite eq \n"
" mrseq r0, msp \n"
" mrsne r0, psp \n"
" mov r1,lr \n"
" mov r2,#7 \n"
" b HardFault_HandlerC \n"
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#7")
A("b HardFault_HandlerC")
);
}

View file

@ -77,10 +77,10 @@
__asm__ __volatile__(
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
"loop%=:" "\n\t"
" subs %[cnt],#1" "\n\t"
EXTRA_NOP_CYCLES "\n\t"
" bne loop%=" "\n\t"
L("loop%=")
A("subs %[cnt],#1")
A(EXTRA_NOP_CYCLES)
A("bne loop%=")
: [cnt]"+r"(cy) // output: +r means input+output
: // input:
: "cc" // clobbers:
@ -141,54 +141,54 @@
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
/* Bit 7 */
" ubfx %[idx],%[txval],#7,#1" "\n\t" /* Place bit 7 in bit 0 of idx*/
A("ubfx %[idx],%[txval],#7,#1") /* Place bit 7 in bit 0 of idx*/
" str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[idx],%[txval],#6,#1" "\n\t" /* Place bit 6 in bit 0 of idx*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[idx],%[txval],#6,#1") /* Place bit 6 in bit 0 of idx*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 6 */
" str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[idx],%[txval],#5,#1" "\n\t" /* Place bit 5 in bit 0 of idx*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[idx],%[txval],#5,#1") /* Place bit 5 in bit 0 of idx*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 5 */
" str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[idx],%[txval],#4,#1" "\n\t" /* Place bit 4 in bit 0 of idx*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[idx],%[txval],#4,#1") /* Place bit 4 in bit 0 of idx*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 4 */
" str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[idx],%[txval],#3,#1" "\n\t" /* Place bit 3 in bit 0 of idx*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[idx],%[txval],#3,#1") /* Place bit 3 in bit 0 of idx*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 3 */
" str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[idx],%[txval],#2,#1" "\n\t" /* Place bit 2 in bit 0 of idx*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[idx],%[txval],#2,#1") /* Place bit 2 in bit 0 of idx*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 2 */
" str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[idx],%[txval],#1,#1" "\n\t" /* Place bit 1 in bit 0 of idx*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[idx],%[txval],#1,#1") /* Place bit 1 in bit 0 of idx*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 1 */
" str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[idx],%[txval],#0,#1" "\n\t" /* Place bit 0 in bit 0 of idx*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[idx],%[txval],#0,#1") /* Place bit 0 in bit 0 of idx*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 0 */
" str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" nop" "\n\t" /* Result will be 0 */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("nop") /* Result will be 0 */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
: [idx]"+r"( idx )
: [txval]"r"( bout ) ,
@ -222,52 +222,52 @@
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
/* bit 7 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#7,#1" "\n\t" /* Store read bit as the bit 7 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#7,#1") /* Store read bit as the bit 7 */
/* bit 6 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#6,#1" "\n\t" /* Store read bit as the bit 6 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#6,#1") /* Store read bit as the bit 6 */
/* bit 5 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#5,#1" "\n\t" /* Store read bit as the bit 5 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#5,#1") /* Store read bit as the bit 5 */
/* bit 4 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#4,#1" "\n\t" /* Store read bit as the bit 4 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#4,#1") /* Store read bit as the bit 4 */
/* bit 3 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#3,#1" "\n\t" /* Store read bit as the bit 3 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#3,#1") /* Store read bit as the bit 3 */
/* bit 2 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#2,#1" "\n\t" /* Store read bit as the bit 2 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#2,#1") /* Store read bit as the bit 2 */
/* bit 1 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#1,#1" "\n\t" /* Store read bit as the bit 1 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#1,#1") /* Store read bit as the bit 1 */
/* bit 0 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#0,#1" "\n\t" /* Store read bit as the bit 0 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#0,#1") /* Store read bit as the bit 0 */
: [bin]"+r"(bin),
[work]"+r"(work)
@ -335,60 +335,60 @@
__asm__ __volatile__(
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
" loop%=:" "\n\t"
" ldrb.w %[txval], [%[ptr]], #1" "\n\t" /* Load value to send, increment buffer */
" mvn %[txval],%[txval]" "\n\t" /* Negate value */
L("loop%=")
A("ldrb.w %[txval], [%[ptr]], #1") /* Load value to send, increment buffer */
A("mvn %[txval],%[txval]") /* Negate value */
/* Bit 7 */
" ubfx %[work],%[txval],#7,#1" "\n\t" /* Place bit 7 in bit 0 of work*/
A("ubfx %[work],%[txval],#7,#1") /* Place bit 7 in bit 0 of work*/
" str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[work],%[txval],#6,#1" "\n\t" /* Place bit 6 in bit 0 of work*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[work],%[txval],#6,#1") /* Place bit 6 in bit 0 of work*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 6 */
" str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[work],%[txval],#5,#1" "\n\t" /* Place bit 5 in bit 0 of work*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[work],%[txval],#5,#1") /* Place bit 5 in bit 0 of work*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 5 */
" str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[work],%[txval],#4,#1" "\n\t" /* Place bit 4 in bit 0 of work*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[work],%[txval],#4,#1") /* Place bit 4 in bit 0 of work*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 4 */
" str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[work],%[txval],#3,#1" "\n\t" /* Place bit 3 in bit 0 of work*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[work],%[txval],#3,#1") /* Place bit 3 in bit 0 of work*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 3 */
" str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[work],%[txval],#2,#1" "\n\t" /* Place bit 2 in bit 0 of work*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[work],%[txval],#2,#1") /* Place bit 2 in bit 0 of work*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 2 */
" str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[work],%[txval],#1,#1" "\n\t" /* Place bit 1 in bit 0 of work*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[work],%[txval],#1,#1") /* Place bit 1 in bit 0 of work*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 1 */
" str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ubfx %[work],%[txval],#0,#1" "\n\t" /* Place bit 0 in bit 0 of work*/
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ubfx %[work],%[txval],#0,#1") /* Place bit 0 in bit 0 of work*/
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
/* Bit 0 */
" str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" subs %[todo],#1" "\n\t" /* Decrement count of pending words to send, update status */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bne.n loop%=" "\n\t" /* Repeat until done */
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("subs %[todo],#1") /* Decrement count of pending words to send, update status */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bne.n loop%=") /* Repeat until done */
: [ptr]"+r" ( ptr ) ,
[todo]"+r" ( todo ) ,
@ -413,59 +413,59 @@
__asm__ __volatile__(
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
" loop%=:" "\n\t"
L("loop%=")
/* bit 7 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#7,#1" "\n\t" /* Store read bit as the bit 7 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#7,#1") /* Store read bit as the bit 7 */
/* bit 6 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#6,#1" "\n\t" /* Store read bit as the bit 6 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#6,#1") /* Store read bit as the bit 6 */
/* bit 5 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#5,#1" "\n\t" /* Store read bit as the bit 5 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#5,#1") /* Store read bit as the bit 5 */
/* bit 4 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#4,#1" "\n\t" /* Store read bit as the bit 4 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#4,#1") /* Store read bit as the bit 4 */
/* bit 3 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#3,#1" "\n\t" /* Store read bit as the bit 3 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#3,#1") /* Store read bit as the bit 3 */
/* bit 2 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#2,#1" "\n\t" /* Store read bit as the bit 2 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#2,#1") /* Store read bit as the bit 2 */
/* bit 1 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#1,#1" "\n\t" /* Store read bit as the bit 1 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#1,#1") /* Store read bit as the bit 1 */
/* bit 0 */
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
" ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
" bfi %[bin],%[work],#0,#1" "\n\t" /* Store read bit as the bit 0 */
A("str %[sck_mask],[%[sck_port]]") /* SODR */
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
A("bfi %[bin],%[work],#0,#1") /* Store read bit as the bit 0 */
" subs %[todo],#1" "\n\t" /* Decrement count of pending words to send, update status */
" strb.w %[bin], [%[ptr]], #1" "\n\t" /* Store read value into buffer, increment buffer pointer */
" bne.n loop%=" "\n\t" /* Repeat until done */
A("subs %[todo],#1") /* Decrement count of pending words to send, update status */
A("strb.w %[bin], [%[ptr]], #1") /* Store read value into buffer, increment buffer pointer */
A("bne.n loop%=") /* Repeat until done */
: [ptr]"+r"(ptr),
[todo]"+r"(todo),

View file

@ -71,8 +71,6 @@ void u8g_SetPILevel_DUE(u8g_t *u8g, uint8_t pin_index, uint8_t level) {
else port->PIO_CODR = mask;
}
#define nop() __asm__ __volatile__("nop;\n\t":::)
void __delay_4cycles(uint32_t cy) __attribute__ ((weak));
FORCE_INLINE void __delay_4cycles(uint32_t cy) { // +1 cycle
@ -85,10 +83,10 @@ FORCE_INLINE void __delay_4cycles(uint32_t cy) { // +1 cycle
__asm__ __volatile__(
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
"loop%=:" "\n\t"
" subs %[cnt],#1" "\n\t"
EXTRA_NOP_CYCLES "\n\t"
" bne loop%=" "\n\t"
L("loop%=")
A("subs %[cnt],#1")
A(EXTRA_NOP_CYCLES)
A("bne loop%=")
: [cnt]"+r"(cy) // output: +r means input+output
: // input:
: "cc" // clobbers:

View file

@ -291,7 +291,7 @@ static inline __attribute__((always_inline)) uint32_t read_psp(void) {
/* Read the current PSP and return its value as a pointer */
uint32_t psp;
__asm volatile (
__asm__ volatile (
" mrs %0, psp \n"
: "=r" (psp) : :
);

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,4,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -444,6 +444,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -433,6 +433,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -433,6 +433,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -433,6 +433,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -433,6 +433,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -433,6 +433,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -438,6 +438,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -433,6 +433,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -431,6 +431,15 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
//
// Use Junction Deviation instead of traditional Jerk Limiting
//
//#define JUNCTION_DEVIATION
#if ENABLED(JUNCTION_DEVIATION)
#define JUNCTION_DEVIATION_FACTOR 0.02
//#define JUNCTION_DEVIATION_INCLUDE_E
#endif
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]

View file

@ -110,6 +110,9 @@
#define STRINGIFY_(M) #M
#define STRINGIFY(M) STRINGIFY_(M)
#define A(CODE) " " CODE "\n\t"
#define L(CODE) CODE ":\n\t"
// Macros for bit masks
#undef _BV
#define _BV(b) (1 << (b))

View file

@ -639,7 +639,7 @@ class DigitalPin {
//------------------------------------------------------------------------------
/** Nop for timing. */
#define nop asm volatile ("nop\n\t")
#define nop __asm__ volatile ("nop")
//------------------------------------------------------------------------------
/** Pin Mode for MISO is input.*/
const bool MISO_MODE = false;

View file

@ -409,7 +409,7 @@ void Planner::init() {
// %8:%7:%6 = interval
// r31:r30: MUST be those registers, and they must point to the inv_tab
" clr %13" "\n\t" // %13 = 0
A("clr %13") // %13 = 0
// Now we must compute
// result = 0xFFFFFF / d
@ -421,122 +421,122 @@ void Planner::init() {
// use Newton-Raphson for the calculation, and will strive to get way less cycles
// for the same result - Using C division, it takes 500cycles to complete .
" clr %3" "\n\t" // idx = 0
" mov %14,%6" "\n\t"
" mov %15,%7" "\n\t"
" mov %16,%8" "\n\t" // nr = interval
" tst %16" "\n\t" // nr & 0xFF0000 == 0 ?
" brne 2f" "\n\t" // No, skip this
" mov %16,%15" "\n\t"
" mov %15,%14" "\n\t" // nr <<= 8, %14 not needed
" subi %3,-8" "\n\t" // idx += 8
" tst %16" "\n\t" // nr & 0xFF0000 == 0 ?
" brne 2f" "\n\t" // No, skip this
" mov %16,%15" "\n\t" // nr <<= 8, %14 not needed
" clr %15" "\n\t" // We clear %14
" subi %3,-8" "\n\t" // idx += 8
A("clr %3") // idx = 0
A("mov %14,%6")
A("mov %15,%7")
A("mov %16,%8") // nr = interval
A("tst %16") // nr & 0xFF0000 == 0 ?
A("brne 2f") // No, skip this
A("mov %16,%15")
A("mov %15,%14") // nr <<= 8, %14 not needed
A("subi %3,-8") // idx += 8
A("tst %16") // nr & 0xFF0000 == 0 ?
A("brne 2f") // No, skip this
A("mov %16,%15") // nr <<= 8, %14 not needed
A("clr %15") // We clear %14
A("subi %3,-8") // idx += 8
// here %16 != 0 and %16:%15 contains at least 9 MSBits, or both %16:%15 are 0
"2:" "\n\t"
" cpi %16,0x10" "\n\t" // (nr & 0xf00000) == 0 ?
" brcc 3f" "\n\t" // No, skip this
" swap %15" "\n\t" // Swap nibbles
" swap %16" "\n\t" // Swap nibbles. Low nibble is 0
" mov %14, %15" "\n\t"
" andi %14,0x0f" "\n\t" // Isolate low nibble
" andi %15,0xf0" "\n\t" // Keep proper nibble in %15
" or %16, %14" "\n\t" // %16:%15 <<= 4
" subi %3,-4" "\n\t" // idx += 4
L("2")
A("cpi %16,0x10") // (nr & 0xF00000) == 0 ?
A("brcc 3f") // No, skip this
A("swap %15") // Swap nibbles
A("swap %16") // Swap nibbles. Low nibble is 0
A("mov %14, %15")
A("andi %14,0x0F") // Isolate low nibble
A("andi %15,0xF0") // Keep proper nibble in %15
A("or %16, %14") // %16:%15 <<= 4
A("subi %3,-4") // idx += 4
"3:" "\n\t"
" cpi %16,0x40" "\n\t" // (nr & 0xc00000) == 0 ?
" brcc 4f" "\n\t" // No, skip this
" add %15,%15" "\n\t"
" adc %16,%16" "\n\t"
" add %15,%15" "\n\t"
" adc %16,%16" "\n\t" // %16:%15 <<= 2
" subi %3,-2" "\n\t" // idx += 2
L("3")
A("cpi %16,0x40") // (nr & 0xC00000) == 0 ?
A("brcc 4f") // No, skip this
A("add %15,%15")
A("adc %16,%16")
A("add %15,%15")
A("adc %16,%16") // %16:%15 <<= 2
A("subi %3,-2") // idx += 2
"4:" "\n\t"
" cpi %16,0x80" "\n\t" // (nr & 0x800000) == 0 ?
" brcc 5f" "\n\t" // No, skip this
" add %15,%15" "\n\t"
" adc %16,%16" "\n\t" // %16:%15 <<= 1
" inc %3" "\n\t" // idx += 1
L("4")
A("cpi %16,0x80") // (nr & 0x800000) == 0 ?
A("brcc 5f") // No, skip this
A("add %15,%15")
A("adc %16,%16") // %16:%15 <<= 1
A("inc %3") // idx += 1
// Now %16:%15 contains its MSBit set to 1, or %16:%15 is == 0. We are now absolutely sure
// we have at least 9 MSBits available to enter the initial estimation table
"5:" "\n\t"
" add %15,%15" "\n\t"
" adc %16,%16" "\n\t" // %16:%15 = tidx = (nr <<= 1), we lose the top MSBit (always set to 1, %16 is the index into the inverse table)
" add r30,%16" "\n\t" // Only use top 8 bits
" adc r31,%13" "\n\t" // r31:r30 = inv_tab + (tidx)
" lpm %14, Z" "\n\t" // %14 = inv_tab[tidx]
" ldi %15, 1" "\n\t" // %15 = 1 %15:%14 = inv_tab[tidx] + 256
L("5")
A("add %15,%15")
A("adc %16,%16") // %16:%15 = tidx = (nr <<= 1), we lose the top MSBit (always set to 1, %16 is the index into the inverse table)
A("add r30,%16") // Only use top 8 bits
A("adc r31,%13") // r31:r30 = inv_tab + (tidx)
A("lpm %14, Z") // %14 = inv_tab[tidx]
A("ldi %15, 1") // %15 = 1 %15:%14 = inv_tab[tidx] + 256
// We must scale the approximation to the proper place
" clr %16" "\n\t" // %16 will always be 0 here
" subi %3,8" "\n\t" // idx == 8 ?
" breq 6f" "\n\t" // yes, no need to scale
" brcs 7f" "\n\t" // If C=1, means idx < 8, result was negative!
A("clr %16") // %16 will always be 0 here
A("subi %3,8") // idx == 8 ?
A("breq 6f") // yes, no need to scale
A("brcs 7f") // If C=1, means idx < 8, result was negative!
// idx > 8, now %3 = idx - 8. We must perform a left shift. idx range:[1-8]
" sbrs %3,0" "\n\t" // shift by 1bit position?
" rjmp 8f" "\n\t" // No
" add %14,%14" "\n\t"
" adc %15,%15" "\n\t" // %15:16 <<= 1
"8:" "\n\t"
" sbrs %3,1" "\n\t" // shift by 2bit position?
" rjmp 9f" "\n\t" // No
" add %14,%14" "\n\t"
" adc %15,%15" "\n\t"
" add %14,%14" "\n\t"
" adc %15,%15" "\n\t" // %15:16 <<= 1
"9:" "\n\t"
" sbrs %3,2" "\n\t" // shift by 4bits position?
" rjmp 16f" "\n\t" // No
" swap %15" "\n\t" // Swap nibbles. lo nibble of %15 will always be 0
" swap %14" "\n\t" // Swap nibbles
" mov %12,%14" "\n\t"
" andi %12,0x0f" "\n\t" // isolate low nibble
" andi %14,0xf0" "\n\t" // and clear it
" or %15,%12" "\n\t" // %15:%16 <<= 4
"16:" "\n\t"
" sbrs %3,3" "\n\t" // shift by 8bits position?
" rjmp 6f" "\n\t" // No, we are done
" mov %16,%15" "\n\t"
" mov %15,%14" "\n\t"
" clr %14" "\n\t"
" jmp 6f" "\n\t"
A("sbrs %3,0") // shift by 1bit position?
A("rjmp 8f") // No
A("add %14,%14")
A("adc %15,%15") // %15:16 <<= 1
L("8")
A("sbrs %3,1") // shift by 2bit position?
A("rjmp 9f") // No
A("add %14,%14")
A("adc %15,%15")
A("add %14,%14")
A("adc %15,%15") // %15:16 <<= 1
L("9")
A("sbrs %3,2") // shift by 4bits position?
A("rjmp 16f") // No
A("swap %15") // Swap nibbles. lo nibble of %15 will always be 0
A("swap %14") // Swap nibbles
A("mov %12,%14")
A("andi %12,0x0F") // isolate low nibble
A("andi %14,0xF0") // and clear it
A("or %15,%12") // %15:%16 <<= 4
L("16")
A("sbrs %3,3") // shift by 8bits position?
A("rjmp 6f") // No, we are done
A("mov %16,%15")
A("mov %15,%14")
A("clr %14")
A("jmp 6f")
// idx < 8, now %3 = idx - 8. Get the count of bits
"7:" "\n\t"
" neg %3" "\n\t" // %3 = -idx = count of bits to move right. idx range:[1...8]
" sbrs %3,0" "\n\t" // shift by 1 bit position ?
" rjmp 10f" "\n\t" // No, skip it
" asr %15" "\n\t" // (bit7 is always 0 here)
" ror %14" "\n\t"
"10:" "\n\t"
" sbrs %3,1" "\n\t" // shift by 2 bit position ?
" rjmp 11f" "\n\t" // No, skip it
" asr %15" "\n\t" // (bit7 is always 0 here)
" ror %14" "\n\t"
" asr %15" "\n\t" // (bit7 is always 0 here)
" ror %14" "\n\t"
"11:" "\n\t"
" sbrs %3,2" "\n\t" // shift by 4 bit position ?
" rjmp 12f" "\n\t" // No, skip it
" swap %15" "\n\t" // Swap nibbles
" andi %14, 0xf0" "\n\t" // Lose the lowest nibble
" swap %14" "\n\t" // Swap nibbles. Upper nibble is 0
" or %14,%15" "\n\t" // Pass nibble from upper byte
" andi %15, 0x0f" "\n\t" // And get rid of that nibble
"12:" "\n\t"
" sbrs %3,3" "\n\t" // shift by 8 bit position ?
" rjmp 6f" "\n\t" // No, skip it
" mov %14,%15" "\n\t"
" clr %15" "\n\t"
"6:" "\n\t" // %16:%15:%14 = initial estimation of 0x1000000 / d
L("7")
A("neg %3") // %3 = -idx = count of bits to move right. idx range:[1...8]
A("sbrs %3,0") // shift by 1 bit position ?
A("rjmp 10f") // No, skip it
A("asr %15") // (bit7 is always 0 here)
A("ror %14")
L("10")
A("sbrs %3,1") // shift by 2 bit position ?
A("rjmp 11f") // No, skip it
A("asr %15") // (bit7 is always 0 here)
A("ror %14")
A("asr %15") // (bit7 is always 0 here)
A("ror %14")
L("11")
A("sbrs %3,2") // shift by 4 bit position ?
A("rjmp 12f") // No, skip it
A("swap %15") // Swap nibbles
A("andi %14, 0xF0") // Lose the lowest nibble
A("swap %14") // Swap nibbles. Upper nibble is 0
A("or %14,%15") // Pass nibble from upper byte
A("andi %15, 0x0F") // And get rid of that nibble
L("12")
A("sbrs %3,3") // shift by 8 bit position ?
A("rjmp 6f") // No, skip it
A("mov %14,%15")
A("clr %15")
L("6") // %16:%15:%14 = initial estimation of 0x1000000 / d
// Now, we must refine the estimation present on %16:%15:%14 using 1 iteration
// of Newton-Raphson. As it has a quadratic convergence, 1 iteration is enough
@ -549,36 +549,36 @@ void Planner::init() {
// %3:%2:%1:%0 = working accumulator
// Compute 1<<25 - x*d. Result should never exceed 25 bits and should always be positive
" clr %0" "\n\t"
" clr %1" "\n\t"
" clr %2" "\n\t"
" ldi %3,2" "\n\t" // %3:%2:%1:%0 = 0x2000000
" mul %6,%14" "\n\t" // r1:r0 = LO(d) * LO(x)
" sub %0,r0" "\n\t"
" sbc %1,r1" "\n\t"
" sbc %2,%13" "\n\t"
" sbc %3,%13" "\n\t" // %3:%2:%1:%0 -= LO(d) * LO(x)
" mul %7,%14" "\n\t" // r1:r0 = MI(d) * LO(x)
" sub %1,r0" "\n\t"
" sbc %2,r1" "\n\t"
" sbc %3,%13" "\n\t" // %3:%2:%1:%0 -= MI(d) * LO(x) << 8
" mul %8,%14" "\n\t" // r1:r0 = HI(d) * LO(x)
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t" // %3:%2:%1:%0 -= MIL(d) * LO(x) << 16
" mul %6,%15" "\n\t" // r1:r0 = LO(d) * MI(x)
" sub %1,r0" "\n\t"
" sbc %2,r1" "\n\t"
" sbc %3,%13" "\n\t" // %3:%2:%1:%0 -= LO(d) * MI(x) << 8
" mul %7,%15" "\n\t" // r1:r0 = MI(d) * MI(x)
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t" // %3:%2:%1:%0 -= MI(d) * MI(x) << 16
" mul %8,%15" "\n\t" // r1:r0 = HI(d) * MI(x)
" sub %3,r0" "\n\t" // %3:%2:%1:%0 -= MIL(d) * MI(x) << 24
" mul %6,%16" "\n\t" // r1:r0 = LO(d) * HI(x)
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t" // %3:%2:%1:%0 -= LO(d) * HI(x) << 16
" mul %7,%16" "\n\t" // r1:r0 = MI(d) * HI(x)
" sub %3,r0" "\n\t" // %3:%2:%1:%0 -= MI(d) * HI(x) << 24
A("clr %0")
A("clr %1")
A("clr %2")
A("ldi %3,2") // %3:%2:%1:%0 = 0x2000000
A("mul %6,%14") // r1:r0 = LO(d) * LO(x)
A("sub %0,r0")
A("sbc %1,r1")
A("sbc %2,%13")
A("sbc %3,%13") // %3:%2:%1:%0 -= LO(d) * LO(x)
A("mul %7,%14") // r1:r0 = MI(d) * LO(x)
A("sub %1,r0")
A("sbc %2,r1" )
A("sbc %3,%13") // %3:%2:%1:%0 -= MI(d) * LO(x) << 8
A("mul %8,%14") // r1:r0 = HI(d) * LO(x)
A("sub %2,r0")
A("sbc %3,r1") // %3:%2:%1:%0 -= MIL(d) * LO(x) << 16
A("mul %6,%15") // r1:r0 = LO(d) * MI(x)
A("sub %1,r0")
A("sbc %2,r1")
A("sbc %3,%13") // %3:%2:%1:%0 -= LO(d) * MI(x) << 8
A("mul %7,%15") // r1:r0 = MI(d) * MI(x)
A("sub %2,r0")
A("sbc %3,r1") // %3:%2:%1:%0 -= MI(d) * MI(x) << 16
A("mul %8,%15") // r1:r0 = HI(d) * MI(x)
A("sub %3,r0") // %3:%2:%1:%0 -= MIL(d) * MI(x) << 24
A("mul %6,%16") // r1:r0 = LO(d) * HI(x)
A("sub %2,r0")
A("sbc %3,r1") // %3:%2:%1:%0 -= LO(d) * HI(x) << 16
A("mul %7,%16") // r1:r0 = MI(d) * HI(x)
A("sub %3,r0") // %3:%2:%1:%0 -= MI(d) * HI(x) << 24
// %3:%2:%1:%0 = (1<<25) - x*d [169]
// We need to multiply that result by x, and we are only interested in the top 24bits of that multiply
@ -588,62 +588,62 @@ void Planner::init() {
// %13 = 0
// result = %11:%10:%9:%5:%4
" mul %14,%0" "\n\t" // r1:r0 = LO(x) * LO(acc)
" mov %4,r1" "\n\t"
" clr %5" "\n\t"
" clr %9" "\n\t"
" clr %10" "\n\t"
" clr %11" "\n\t" // %11:%10:%9:%5:%4 = LO(x) * LO(acc) >> 8
" mul %15,%0" "\n\t" // r1:r0 = MI(x) * LO(acc)
" add %4,r0" "\n\t"
" adc %5,r1" "\n\t"
" adc %9,%13" "\n\t"
" adc %10,%13" "\n\t"
" adc %11,%13" "\n\t" // %11:%10:%9:%5:%4 += MI(x) * LO(acc)
" mul %16,%0" "\n\t" // r1:r0 = HI(x) * LO(acc)
" add %5,r0" "\n\t"
" adc %9,r1" "\n\t"
" adc %10,%13" "\n\t"
" adc %11,%13" "\n\t" // %11:%10:%9:%5:%4 += MI(x) * LO(acc) << 8
A("mul %14,%0") // r1:r0 = LO(x) * LO(acc)
A("mov %4,r1")
A("clr %5")
A("clr %9")
A("clr %10")
A("clr %11") // %11:%10:%9:%5:%4 = LO(x) * LO(acc) >> 8
A("mul %15,%0") // r1:r0 = MI(x) * LO(acc)
A("add %4,r0")
A("adc %5,r1")
A("adc %9,%13")
A("adc %10,%13")
A("adc %11,%13") // %11:%10:%9:%5:%4 += MI(x) * LO(acc)
A("mul %16,%0") // r1:r0 = HI(x) * LO(acc)
A("add %5,r0")
A("adc %9,r1")
A("adc %10,%13")
A("adc %11,%13") // %11:%10:%9:%5:%4 += MI(x) * LO(acc) << 8
" mul %14,%1" "\n\t" // r1:r0 = LO(x) * MIL(acc)
" add %4,r0" "\n\t"
" adc %5,r1" "\n\t"
" adc %9,%13" "\n\t"
" adc %10,%13" "\n\t"
" adc %11,%13" "\n\t" // %11:%10:%9:%5:%4 = LO(x) * MIL(acc)
" mul %15,%1" "\n\t" // r1:r0 = MI(x) * MIL(acc)
" add %5,r0" "\n\t"
" adc %9,r1" "\n\t"
" adc %10,%13" "\n\t"
" adc %11,%13" "\n\t" // %11:%10:%9:%5:%4 += MI(x) * MIL(acc) << 8
" mul %16,%1" "\n\t" // r1:r0 = HI(x) * MIL(acc)
" add %9,r0" "\n\t"
" adc %10,r1" "\n\t"
" adc %11,%13" "\n\t" // %11:%10:%9:%5:%4 += MI(x) * MIL(acc) << 16
A("mul %14,%1") // r1:r0 = LO(x) * MIL(acc)
A("add %4,r0")
A("adc %5,r1")
A("adc %9,%13")
A("adc %10,%13")
A("adc %11,%13") // %11:%10:%9:%5:%4 = LO(x) * MIL(acc)
A("mul %15,%1") // r1:r0 = MI(x) * MIL(acc)
A("add %5,r0")
A("adc %9,r1")
A("adc %10,%13")
A("adc %11,%13") // %11:%10:%9:%5:%4 += MI(x) * MIL(acc) << 8
A("mul %16,%1") // r1:r0 = HI(x) * MIL(acc)
A("add %9,r0")
A("adc %10,r1")
A("adc %11,%13") // %11:%10:%9:%5:%4 += MI(x) * MIL(acc) << 16
" mul %14,%2" "\n\t" // r1:r0 = LO(x) * MIH(acc)
" add %5,r0" "\n\t"
" adc %9,r1" "\n\t"
" adc %10,%13" "\n\t"
" adc %11,%13" "\n\t" // %11:%10:%9:%5:%4 = LO(x) * MIH(acc) << 8
" mul %15,%2" "\n\t" // r1:r0 = MI(x) * MIH(acc)
" add %9,r0" "\n\t"
" adc %10,r1" "\n\t"
" adc %11,%13" "\n\t" // %11:%10:%9:%5:%4 += MI(x) * MIH(acc) << 16
" mul %16,%2" "\n\t" // r1:r0 = HI(x) * MIH(acc)
" add %10,r0" "\n\t"
" adc %11,r1" "\n\t" // %11:%10:%9:%5:%4 += MI(x) * MIH(acc) << 24
A("mul %14,%2") // r1:r0 = LO(x) * MIH(acc)
A("add %5,r0")
A("adc %9,r1")
A("adc %10,%13")
A("adc %11,%13") // %11:%10:%9:%5:%4 = LO(x) * MIH(acc) << 8
A("mul %15,%2") // r1:r0 = MI(x) * MIH(acc)
A("add %9,r0")
A("adc %10,r1")
A("adc %11,%13") // %11:%10:%9:%5:%4 += MI(x) * MIH(acc) << 16
A("mul %16,%2") // r1:r0 = HI(x) * MIH(acc)
A("add %10,r0")
A("adc %11,r1") // %11:%10:%9:%5:%4 += MI(x) * MIH(acc) << 24
" mul %14,%3" "\n\t" // r1:r0 = LO(x) * HI(acc)
" add %9,r0" "\n\t"
" adc %10,r1" "\n\t"
" adc %11,%13" "\n\t" // %11:%10:%9:%5:%4 = LO(x) * HI(acc) << 16
" mul %15,%3" "\n\t" // r1:r0 = MI(x) * HI(acc)
" add %10,r0" "\n\t"
" adc %11,r1" "\n\t" // %11:%10:%9:%5:%4 += MI(x) * HI(acc) << 24
" mul %16,%3" "\n\t" // r1:r0 = HI(x) * HI(acc)
" add %11,r0" "\n\t" // %11:%10:%9:%5:%4 += MI(x) * HI(acc) << 32
A("mul %14,%3") // r1:r0 = LO(x) * HI(acc)
A("add %9,r0")
A("adc %10,r1")
A("adc %11,%13") // %11:%10:%9:%5:%4 = LO(x) * HI(acc) << 16
A("mul %15,%3") // r1:r0 = MI(x) * HI(acc)
A("add %10,r0")
A("adc %11,r1") // %11:%10:%9:%5:%4 += MI(x) * HI(acc) << 24
A("mul %16,%3") // r1:r0 = HI(x) * HI(acc)
A("add %11,r0") // %11:%10:%9:%5:%4 += MI(x) * HI(acc) << 32
// At this point, %11:%10:%9 contains the new estimation of x.
@ -651,54 +651,54 @@ void Planner::init() {
// (1<<24) - x*d
// %11:%10:%9 = x
// %8:%7:%6 = d = interval" "\n\t"
" ldi %3,1" "\n\t"
" clr %2" "\n\t"
" clr %1" "\n\t"
" clr %0" "\n\t" // %3:%2:%1:%0 = 0x1000000
" mul %6,%9" "\n\t" // r1:r0 = LO(d) * LO(x)
" sub %0,r0" "\n\t"
" sbc %1,r1" "\n\t"
" sbc %2,%13" "\n\t"
" sbc %3,%13" "\n\t" // %3:%2:%1:%0 -= LO(d) * LO(x)
" mul %7,%9" "\n\t" // r1:r0 = MI(d) * LO(x)
" sub %1,r0" "\n\t"
" sbc %2,r1" "\n\t"
" sbc %3,%13" "\n\t" // %3:%2:%1:%0 -= MI(d) * LO(x) << 8
" mul %8,%9" "\n\t" // r1:r0 = HI(d) * LO(x)
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t" // %3:%2:%1:%0 -= MIL(d) * LO(x) << 16
" mul %6,%10" "\n\t" // r1:r0 = LO(d) * MI(x)
" sub %1,r0" "\n\t"
" sbc %2,r1" "\n\t"
" sbc %3,%13" "\n\t" // %3:%2:%1:%0 -= LO(d) * MI(x) << 8
" mul %7,%10" "\n\t" // r1:r0 = MI(d) * MI(x)
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t" // %3:%2:%1:%0 -= MI(d) * MI(x) << 16
" mul %8,%10" "\n\t" // r1:r0 = HI(d) * MI(x)
" sub %3,r0" "\n\t" // %3:%2:%1:%0 -= MIL(d) * MI(x) << 24
" mul %6,%11" "\n\t" // r1:r0 = LO(d) * HI(x)
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t" // %3:%2:%1:%0 -= LO(d) * HI(x) << 16
" mul %7,%11" "\n\t" // r1:r0 = MI(d) * HI(x)
" sub %3,r0" "\n\t" // %3:%2:%1:%0 -= MI(d) * HI(x) << 24
A("ldi %3,1")
A("clr %2")
A("clr %1")
A("clr %0") // %3:%2:%1:%0 = 0x1000000
A("mul %6,%9") // r1:r0 = LO(d) * LO(x)
A("sub %0,r0")
A("sbc %1,r1")
A("sbc %2,%13")
A("sbc %3,%13") // %3:%2:%1:%0 -= LO(d) * LO(x)
A("mul %7,%9") // r1:r0 = MI(d) * LO(x)
A("sub %1,r0")
A("sbc %2,r1")
A("sbc %3,%13") // %3:%2:%1:%0 -= MI(d) * LO(x) << 8
A("mul %8,%9") // r1:r0 = HI(d) * LO(x)
A("sub %2,r0")
A("sbc %3,r1") // %3:%2:%1:%0 -= MIL(d) * LO(x) << 16
A("mul %6,%10") // r1:r0 = LO(d) * MI(x)
A("sub %1,r0")
A("sbc %2,r1")
A("sbc %3,%13") // %3:%2:%1:%0 -= LO(d) * MI(x) << 8
A("mul %7,%10") // r1:r0 = MI(d) * MI(x)
A("sub %2,r0")
A("sbc %3,r1") // %3:%2:%1:%0 -= MI(d) * MI(x) << 16
A("mul %8,%10") // r1:r0 = HI(d) * MI(x)
A("sub %3,r0") // %3:%2:%1:%0 -= MIL(d) * MI(x) << 24
A("mul %6,%11") // r1:r0 = LO(d) * HI(x)
A("sub %2,r0")
A("sbc %3,r1") // %3:%2:%1:%0 -= LO(d) * HI(x) << 16
A("mul %7,%11") // r1:r0 = MI(d) * HI(x)
A("sub %3,r0") // %3:%2:%1:%0 -= MI(d) * HI(x) << 24
// %3:%2:%1:%0 = r = (1<<24) - x*d
// %8:%7:%6 = d = interval
// Perform the final correction
" sub %0,%6" "\n\t"
" sbc %1,%7" "\n\t"
" sbc %2,%8" "\n\t" // r -= d
" brcs 14f" "\n\t" // if ( r >= d)
A("sub %0,%6")
A("sbc %1,%7")
A("sbc %2,%8") // r -= d
A("brcs 14f") // if ( r >= d)
// %11:%10:%9 = x
" ldi %3,1" "\n\t"
" add %9,%3" "\n\t"
" adc %10,%13" "\n\t"
" adc %11,%13" "\n\t" // x++
"14:" "\n\t"
A("ldi %3,1")
A("add %9,%3")
A("adc %10,%13")
A("adc %11,%13") // x++
L("14")
// Estimation is done. %11:%10:%9 = x
" clr __zero_reg__" "\n\t" // Make C runtime happy
A("clr __zero_reg__") // Make C runtime happy
// [211 cycles total]
: "=r" (r2),
"=r" (r3),
@ -787,8 +787,8 @@ void Planner::calculate_trapezoid_for_block(block_t* const block, const float &e
#if ENABLED(BEZIER_JERK_CONTROL)
// Jerk controlled speed requires to express speed versus time, NOT steps
uint32_t acceleration_time = ((float)(cruise_rate - initial_rate) / accel) * HAL_STEPPER_TIMER_RATE,
deceleration_time = ((float)(cruise_rate - final_rate) / accel) * HAL_STEPPER_TIMER_RATE;
uint32_t acceleration_time = ((float)(cruise_rate - initial_rate) / accel) * (HAL_STEPPER_TIMER_RATE),
deceleration_time = ((float)(cruise_rate - final_rate) / accel) * (HAL_STEPPER_TIMER_RATE);
// And to offload calculations from the ISR, we also calculate the inverse of those times here
uint32_t acceleration_time_inverse = get_period_inverse(acceleration_time);
@ -1864,129 +1864,161 @@ void Planner::_buffer_steps(const int32_t (&target)[XYZE]
}
#endif
// Initial limit on the segment entry velocity
float vmax_junction;
float vmax_junction; // Initial limit on the segment entry velocity
#if 0 // Use old jerk for now
#if ENABLED(JUNCTION_DEVIATION)
float junction_deviation = 0.1;
/**
* Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
* Let a circle be tangent to both previous and current path line segments, where the junction
* deviation is defined as the distance from the junction to the closest edge of the circle,
* colinear with the circle center. The circular segment joining the two paths represents the
* path of centripetal acceleration. Solve for max velocity based on max acceleration about the
* radius of the circle, defined indirectly by junction deviation. This may be also viewed as
* path width or max_jerk in the previous Grbl version. This approach does not actually deviate
* from path, but used as a robust way to compute cornering speeds, as it takes into account the
* nonlinearities of both the junction angle and junction velocity.
*
* NOTE: If the junction deviation value is finite, Grbl executes the motions in an exact path
* mode (G61). If the junction deviation value is zero, Grbl will execute the motion in an exact
* stop mode (G61.1) manner. In the future, if continuous mode (G64) is desired, the math here
* is exactly the same. Instead of motioning all the way to junction point, the machine will
* just follow the arc circle defined here. The Arduino doesn't have the CPU cycles to perform
* a continuous mode path, but ARM-based microcontrollers most certainly do.
*
* NOTE: The max junction speed is a fixed value, since machine acceleration limits cannot be
* changed dynamically during operation nor can the line move geometry. This must be kept in
* memory in the event of a feedrate override changing the nominal speeds of blocks, which can
* change the overall maximum entry speed conditions of all blocks.
*/
// Compute path unit vector
double unit_vec[XYZ] = {
// Unit vector of previous path line segment
static float previous_unit_vec[
#if ENABLED(JUNCTION_DEVIATION_INCLUDE_E)
XYZE
#else
XYZ
#endif
];
float unit_vec[] = {
delta_mm[A_AXIS] * inverse_millimeters,
delta_mm[B_AXIS] * inverse_millimeters,
delta_mm[C_AXIS] * inverse_millimeters
#if ENABLED(JUNCTION_DEVIATION_INCLUDE_E)
, delta_mm[E_AXIS] * inverse_millimeters
#endif
};
/*
Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
Let a circle be tangent to both previous and current path line segments, where the junction
deviation is defined as the distance from the junction to the closest edge of the circle,
collinear with the circle center.
The circular segment joining the two paths represents the path of centripetal acceleration.
Solve for max velocity based on max acceleration about the radius of the circle, defined
indirectly by junction deviation.
This may be also viewed as path width or max_jerk in the previous grbl version. This approach
does not actually deviate from path, but used as a robust way to compute cornering speeds, as
it takes into account the nonlinearities of both the junction angle and junction velocity.
*/
vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed
// Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.
if (moves_queued && !UNEAR_ZERO(previous_nominal_speed)) {
// Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
// NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
const float cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
- previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
- previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS];
// Skip and use default max junction speed for 0 degree acute junction.
if (cos_theta < 0.95) {
vmax_junction = min(previous_nominal_speed, block->nominal_speed);
// Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds.
if (cos_theta > -0.95) {
// Compute maximum junction velocity based on maximum acceleration and junction deviation
float sin_theta_d2 = SQRT(0.5 * (1.0 - cos_theta)); // Trig half angle identity. Always positive.
NOMORE(vmax_junction, SQRT(block->acceleration * junction_deviation * sin_theta_d2 / (1.0 - sin_theta_d2)));
float junction_cos_theta = -previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
-previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
-previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS]
#if ENABLED(JUNCTION_DEVIATION_INCLUDE_E)
-previous_unit_vec[E_AXIS] * unit_vec[E_AXIS]
#endif
;
// NOTE: Computed without any expensive trig, sin() or acos(), by trig half angle identity of cos(theta).
if (junction_cos_theta > 0.999999) {
// For a 0 degree acute junction, just set minimum junction speed.
vmax_junction = MINIMUM_PLANNER_SPEED;
}
else {
junction_cos_theta = max(junction_cos_theta, -0.999999); // Check for numerical round-off to avoid divide by zero.
const float sin_theta_d2 = SQRT(0.5 * (1.0 - junction_cos_theta)); // Trig half angle identity. Always positive.
// TODO: Technically, the acceleration used in calculation needs to be limited by the minimum of the
// two junctions. However, this shouldn't be a significant problem except in extreme circumstances.
vmax_junction = SQRT((block->acceleration * JUNCTION_DEVIATION_FACTOR * sin_theta_d2) / (1.0 - sin_theta_d2));
}
vmax_junction = MIN3(vmax_junction, block->nominal_speed, previous_nominal_speed);
}
else // Init entry speed to zero. Assume it starts from rest. Planner will correct this later.
vmax_junction = 0.0;
COPY(previous_unit_vec, unit_vec);
#else // Classic Jerk Limiting
/**
* Adapted from Průša MKS firmware
* https://github.com/prusa3d/Prusa-Firmware
*
* Start with a safe speed (from which the machine may halt to stop immediately).
*/
// Exit speed limited by a jerk to full halt of a previous last segment
static float previous_safe_speed;
float safe_speed = block->nominal_speed;
uint8_t limited = 0;
LOOP_XYZE(i) {
const float jerk = FABS(current_speed[i]), maxj = max_jerk[i];
if (jerk > maxj) {
if (limited) {
const float mjerk = maxj * block->nominal_speed;
if (jerk * safe_speed > mjerk) safe_speed = mjerk / jerk;
}
else {
++limited;
safe_speed = maxj;
}
}
}
#endif
/**
* Adapted from Průša MKS firmware
* https://github.com/prusa3d/Prusa-Firmware
*
* Start with a safe speed (from which the machine may halt to stop immediately).
*/
if (moves_queued && !UNEAR_ZERO(previous_nominal_speed)) {
// Estimate a maximum velocity allowed at a joint of two successive segments.
// If this maximum velocity allowed is lower than the minimum of the entry / exit safe velocities,
// then the machine is not coasting anymore and the safe entry / exit velocities shall be used.
// Exit speed limited by a jerk to full halt of a previous last segment
static float previous_safe_speed;
// The junction velocity will be shared between successive segments. Limit the junction velocity to their minimum.
// Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
vmax_junction = min(block->nominal_speed, previous_nominal_speed);
float safe_speed = block->nominal_speed;
uint8_t limited = 0;
LOOP_XYZE(i) {
const float jerk = FABS(current_speed[i]), maxj = max_jerk[i];
if (jerk > maxj) {
if (limited) {
const float mjerk = maxj * block->nominal_speed;
if (jerk * safe_speed > mjerk) safe_speed = mjerk / jerk;
}
else {
++limited;
safe_speed = maxj;
// Factor to multiply the previous / current nominal velocities to get componentwise limited velocities.
float v_factor = 1;
limited = 0;
// Now limit the jerk in all axes.
const float smaller_speed_factor = vmax_junction / previous_nominal_speed;
LOOP_XYZE(axis) {
// Limit an axis. We have to differentiate: coasting, reversal of an axis, full stop.
float v_exit = previous_speed[axis] * smaller_speed_factor,
v_entry = current_speed[axis];
if (limited) {
v_exit *= v_factor;
v_entry *= v_factor;
}
// Calculate jerk depending on whether the axis is coasting in the same direction or reversing.
const float jerk = (v_exit > v_entry)
? // coasting axis reversal
( (v_entry > 0 || v_exit < 0) ? (v_exit - v_entry) : max(v_exit, -v_entry) )
: // v_exit <= v_entry coasting axis reversal
( (v_entry < 0 || v_exit > 0) ? (v_entry - v_exit) : max(-v_exit, v_entry) );
if (jerk > max_jerk[axis]) {
v_factor *= max_jerk[axis] / jerk;
++limited;
}
}
if (limited) vmax_junction *= v_factor;
// Now the transition velocity is known, which maximizes the shared exit / entry velocity while
// respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
const float vmax_junction_threshold = vmax_junction * 0.99f;
if (previous_safe_speed > vmax_junction_threshold && safe_speed > vmax_junction_threshold)
vmax_junction = safe_speed;
}
}
if (moves_queued && !UNEAR_ZERO(previous_nominal_speed)) {
// Estimate a maximum velocity allowed at a joint of two successive segments.
// If this maximum velocity allowed is lower than the minimum of the entry / exit safe velocities,
// then the machine is not coasting anymore and the safe entry / exit velocities shall be used.
// The junction velocity will be shared between successive segments. Limit the junction velocity to their minimum.
// Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
vmax_junction = min(block->nominal_speed, previous_nominal_speed);
// Factor to multiply the previous / current nominal velocities to get componentwise limited velocities.
float v_factor = 1;
limited = 0;
// Now limit the jerk in all axes.
const float smaller_speed_factor = vmax_junction / previous_nominal_speed;
LOOP_XYZE(axis) {
// Limit an axis. We have to differentiate: coasting, reversal of an axis, full stop.
float v_exit = previous_speed[axis] * smaller_speed_factor,
v_entry = current_speed[axis];
if (limited) {
v_exit *= v_factor;
v_entry *= v_factor;
}
// Calculate jerk depending on whether the axis is coasting in the same direction or reversing.
const float jerk = (v_exit > v_entry)
? // coasting axis reversal
( (v_entry > 0 || v_exit < 0) ? (v_exit - v_entry) : max(v_exit, -v_entry) )
: // v_exit <= v_entry coasting axis reversal
( (v_entry < 0 || v_exit > 0) ? (v_entry - v_exit) : max(-v_exit, v_entry) );
if (jerk > max_jerk[axis]) {
v_factor *= max_jerk[axis] / jerk;
++limited;
}
}
if (limited) vmax_junction *= v_factor;
// Now the transition velocity is known, which maximizes the shared exit / entry velocity while
// respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
const float vmax_junction_threshold = vmax_junction * 0.99f;
if (previous_safe_speed > vmax_junction_threshold && safe_speed > vmax_junction_threshold)
else
vmax_junction = safe_speed;
}
else
vmax_junction = safe_speed;
previous_safe_speed = safe_speed;
#endif // Classic Jerk Limiting
// Max entry speed of this block equals the max exit speed of the previous block.
block->max_entry_speed = vmax_junction;
@ -2010,7 +2042,6 @@ void Planner::_buffer_steps(const int32_t (&target)[XYZE]
// Update previous path unit_vector and nominal speed
COPY(previous_speed, current_speed);
previous_nominal_speed = block->nominal_speed;
previous_safe_speed = safe_speed;
// Move buffer head
block_buffer_head = next_buffer_head;

View file

@ -581,68 +581,68 @@ void Stepper::set_directions() {
/* %10 (must be high register!)*/
/* Store initial velocity*/
" sts bezier_F, %0" "\n\t"
" sts bezier_F+1, %1" "\n\t"
" sts bezier_F+2, %10" "\n\t" /* bezier_F = %10:%1:%0 = v0 */
A("sts bezier_F, %0")
A("sts bezier_F+1, %1")
A("sts bezier_F+2, %10") /* bezier_F = %10:%1:%0 = v0 */
/* Get delta speed */
" ldi %2,-1" "\n\t" /* %2 = 0xff, means A_negative = true */
" clr %8" "\n\t" /* %8 = 0 */
" sub %0,%3" "\n\t"
" sbc %1,%4" "\n\t"
" sbc %10,%5" "\n\t" /* v0 -= v1, C=1 if result is negative */
" brcc 1f" "\n\t" /* branch if result is positive (C=0), that means v0 >= v1 */
A("ldi %2,-1") /* %2 = 0xFF, means A_negative = true */
A("clr %8") /* %8 = 0 */
A("sub %0,%3")
A("sbc %1,%4")
A("sbc %10,%5") /* v0 -= v1, C=1 if result is negative */
A("brcc 1f") /* branch if result is positive (C=0), that means v0 >= v1 */
/* Result was negative, get the absolute value*/
" com %10" "\n\t"
" com %1" "\n\t"
" neg %0" "\n\t"
" sbc %1,%2" "\n\t"
" sbc %10,%2" "\n\t" /* %10:%1:%0 +1 -> %10:%1:%0 = -(v0 - v1) = (v1 - v0) */
" clr %2" "\n\t" /* %2 = 0, means A_negative = false */
A("com %10")
A("com %1")
A("neg %0")
A("sbc %1,%2")
A("sbc %10,%2") /* %10:%1:%0 +1 -> %10:%1:%0 = -(v0 - v1) = (v1 - v0) */
A("clr %2") /* %2 = 0, means A_negative = false */
/* Store negative flag*/
"1:" "\n\t"
" sts A_negative, %2" "\n\t" /* Store negative flag */
L("1")
A("sts A_negative, %2") /* Store negative flag */
/* Compute coefficients A,B and C [20 cycles worst case]*/
" ldi %9,6" "\n\t" /* %9 = 6 */
" mul %0,%9" "\n\t" /* r1:r0 = 6*LO(v0-v1) */
" sts bezier_A, r0" "\n\t"
" mov %6,r1" "\n\t"
" clr %7" "\n\t" /* %7:%6:r0 = 6*LO(v0-v1) */
" mul %1,%9" "\n\t" /* r1:r0 = 6*MI(v0-v1) */
" add %6,r0" "\n\t"
" adc %7,r1" "\n\t" /* %7:%6:?? += 6*MI(v0-v1) << 8 */
" mul %10,%9" "\n\t" /* r1:r0 = 6*HI(v0-v1) */
" add %7,r0" "\n\t" /* %7:%6:?? += 6*HI(v0-v1) << 16 */
" sts bezier_A+1, %6" "\n\t"
" sts bezier_A+2, %7" "\n\t" /* bezier_A = %7:%6:?? = 6*(v0-v1) [35 cycles worst] */
A("ldi %9,6") /* %9 = 6 */
A("mul %0,%9") /* r1:r0 = 6*LO(v0-v1) */
A("sts bezier_A, r0")
A("mov %6,r1")
A("clr %7") /* %7:%6:r0 = 6*LO(v0-v1) */
A("mul %1,%9") /* r1:r0 = 6*MI(v0-v1) */
A("add %6,r0")
A("adc %7,r1") /* %7:%6:?? += 6*MI(v0-v1) << 8 */
A("mul %10,%9") /* r1:r0 = 6*HI(v0-v1) */
A("add %7,r0") /* %7:%6:?? += 6*HI(v0-v1) << 16 */
A("sts bezier_A+1, %6")
A("sts bezier_A+2, %7") /* bezier_A = %7:%6:?? = 6*(v0-v1) [35 cycles worst] */
" ldi %9,15" "\n\t" /* %9 = 15 */
" mul %0,%9" "\n\t" /* r1:r0 = 5*LO(v0-v1) */
" sts bezier_B, r0" "\n\t"
" mov %6,r1" "\n\t"
" clr %7" "\n\t" /* %7:%6:?? = 5*LO(v0-v1) */
" mul %1,%9" "\n\t" /* r1:r0 = 5*MI(v0-v1) */
" add %6,r0" "\n\t"
" adc %7,r1" "\n\t" /* %7:%6:?? += 5*MI(v0-v1) << 8 */
" mul %10,%9" "\n\t" /* r1:r0 = 5*HI(v0-v1) */
" add %7,r0" "\n\t" /* %7:%6:?? += 5*HI(v0-v1) << 16 */
" sts bezier_B+1, %6" "\n\t"
" sts bezier_B+2, %7" "\n\t" /* bezier_B = %7:%6:?? = 5*(v0-v1) [50 cycles worst] */
A("ldi %9,15") /* %9 = 15 */
A("mul %0,%9") /* r1:r0 = 5*LO(v0-v1) */
A("sts bezier_B, r0")
A("mov %6,r1")
A("clr %7") /* %7:%6:?? = 5*LO(v0-v1) */
A("mul %1,%9") /* r1:r0 = 5*MI(v0-v1) */
A("add %6,r0")
A("adc %7,r1") /* %7:%6:?? += 5*MI(v0-v1) << 8 */
A("mul %10,%9") /* r1:r0 = 5*HI(v0-v1) */
A("add %7,r0") /* %7:%6:?? += 5*HI(v0-v1) << 16 */
A("sts bezier_B+1, %6")
A("sts bezier_B+2, %7") /* bezier_B = %7:%6:?? = 5*(v0-v1) [50 cycles worst] */
" ldi %9,10" "\n\t" /* %9 = 10 */
" mul %0,%9" "\n\t" /* r1:r0 = 10*LO(v0-v1) */
" sts bezier_C, r0" "\n\t"
" mov %6,r1" "\n\t"
" clr %7" "\n\t" /* %7:%6:?? = 10*LO(v0-v1) */
" mul %1,%9" "\n\t" /* r1:r0 = 10*MI(v0-v1) */
" add %6,r0" "\n\t"
" adc %7,r1" "\n\t" /* %7:%6:?? += 10*MI(v0-v1) << 8 */
" mul %10,%9" "\n\t" /* r1:r0 = 10*HI(v0-v1) */
" add %7,r0" "\n\t" /* %7:%6:?? += 10*HI(v0-v1) << 16 */
" sts bezier_C+1, %6" "\n\t"
A("ldi %9,10") /* %9 = 10 */
A("mul %0,%9") /* r1:r0 = 10*LO(v0-v1) */
A("sts bezier_C, r0")
A("mov %6,r1")
A("clr %7") /* %7:%6:?? = 10*LO(v0-v1) */
A("mul %1,%9") /* r1:r0 = 10*MI(v0-v1) */
A("add %6,r0")
A("adc %7,r1") /* %7:%6:?? += 10*MI(v0-v1) << 8 */
A("mul %10,%9") /* r1:r0 = 10*HI(v0-v1) */
A("add %7,r0") /* %7:%6:?? += 10*HI(v0-v1) << 16 */
A("sts bezier_C+1, %6")
" sts bezier_C+2, %7" /* bezier_C = %7:%6:?? = 10*(v0-v1) [65 cycles worst] */
: "+r" (r2),
"+d" (r3),
@ -674,358 +674,358 @@ void Stepper::set_directions() {
__asm__ __volatile(
/* umul24x24to16hi(t, bezier_AV, curr_step); t: Range 0 - 1^16 = 16 bits*/
" lds %9,bezier_AV" "\n\t" /* %9 = LO(AV)*/
" mul %9,%2" "\n\t" /* r1:r0 = LO(bezier_AV)*LO(curr_step)*/
" mov %7,r1" "\n\t" /* %7 = LO(bezier_AV)*LO(curr_step) >> 8*/
" clr %8" "\n\t" /* %8:%7 = LO(bezier_AV)*LO(curr_step) >> 8*/
" lds %10,bezier_AV+1" "\n\t" /* %10 = MI(AV)*/
" mul %10,%2" "\n\t" /* r1:r0 = MI(bezier_AV)*LO(curr_step)*/
" add %7,r0" "\n\t"
" adc %8,r1" "\n\t" /* %8:%7 += MI(bezier_AV)*LO(curr_step)*/
" lds r1,bezier_AV+2" "\n\t" /* r11 = HI(AV)*/
" mul r1,%2" "\n\t" /* r1:r0 = HI(bezier_AV)*LO(curr_step)*/
" add %8,r0" "\n\t" /* %8:%7 += HI(bezier_AV)*LO(curr_step) << 8*/
" mul %9,%3" "\n\t" /* r1:r0 = LO(bezier_AV)*MI(curr_step)*/
" add %7,r0" "\n\t"
" adc %8,r1" "\n\t" /* %8:%7 += LO(bezier_AV)*MI(curr_step)*/
" mul %10,%3" "\n\t" /* r1:r0 = MI(bezier_AV)*MI(curr_step)*/
" add %8,r0" "\n\t" /* %8:%7 += LO(bezier_AV)*MI(curr_step) << 8*/
" mul %9,%4" "\n\t" /* r1:r0 = LO(bezier_AV)*HI(curr_step)*/
" add %8,r0" "\n\t" /* %8:%7 += LO(bezier_AV)*HI(curr_step) << 8*/
A("lds %9,bezier_AV") /* %9 = LO(AV)*/
A("mul %9,%2") /* r1:r0 = LO(bezier_AV)*LO(curr_step)*/
A("mov %7,r1") /* %7 = LO(bezier_AV)*LO(curr_step) >> 8*/
A("clr %8") /* %8:%7 = LO(bezier_AV)*LO(curr_step) >> 8*/
A("lds %10,bezier_AV+1") /* %10 = MI(AV)*/
A("mul %10,%2") /* r1:r0 = MI(bezier_AV)*LO(curr_step)*/
A("add %7,r0")
A("adc %8,r1") /* %8:%7 += MI(bezier_AV)*LO(curr_step)*/
A("lds r1,bezier_AV+2") /* r11 = HI(AV)*/
A("mul r1,%2") /* r1:r0 = HI(bezier_AV)*LO(curr_step)*/
A("add %8,r0") /* %8:%7 += HI(bezier_AV)*LO(curr_step) << 8*/
A("mul %9,%3") /* r1:r0 = LO(bezier_AV)*MI(curr_step)*/
A("add %7,r0")
A("adc %8,r1") /* %8:%7 += LO(bezier_AV)*MI(curr_step)*/
A("mul %10,%3") /* r1:r0 = MI(bezier_AV)*MI(curr_step)*/
A("add %8,r0") /* %8:%7 += LO(bezier_AV)*MI(curr_step) << 8*/
A("mul %9,%4") /* r1:r0 = LO(bezier_AV)*HI(curr_step)*/
A("add %8,r0") /* %8:%7 += LO(bezier_AV)*HI(curr_step) << 8*/
/* %8:%7 = t*/
/* uint16_t f = t;*/
" mov %5,%7" "\n\t" /* %6:%5 = f*/
" mov %6,%8" "\n\t"
A("mov %5,%7") /* %6:%5 = f*/
A("mov %6,%8")
/* %6:%5 = f*/
/* umul16x16to16hi(f, f, t); / Range 16 bits (unsigned) [17] */
" mul %5,%7" "\n\t" /* r1:r0 = LO(f) * LO(t)*/
" mov %9,r1" "\n\t" /* store MIL(LO(f) * LO(t)) in %9, we need it for rounding*/
" clr %10" "\n\t" /* %10 = 0*/
" clr %11" "\n\t" /* %11 = 0*/
" mul %5,%8" "\n\t" /* r1:r0 = LO(f) * HI(t)*/
" add %9,r0" "\n\t" /* %9 += LO(LO(f) * HI(t))*/
" adc %10,r1" "\n\t" /* %10 = HI(LO(f) * HI(t))*/
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%7" "\n\t" /* r1:r0 = HI(f) * LO(t)*/
" add %9,r0" "\n\t" /* %9 += LO(HI(f) * LO(t))*/
" adc %10,r1" "\n\t" /* %10 += HI(HI(f) * LO(t)) */
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%8" "\n\t" /* r1:r0 = HI(f) * HI(t)*/
" add %10,r0" "\n\t" /* %10 += LO(HI(f) * HI(t))*/
" adc %11,r1" "\n\t" /* %11 += HI(HI(f) * HI(t))*/
" mov %5,%10" "\n\t" /* %6:%5 = */
" mov %6,%11" "\n\t" /* f = %10:%11*/
A("mul %5,%7") /* r1:r0 = LO(f) * LO(t)*/
A("mov %9,r1") /* store MIL(LO(f) * LO(t)) in %9, we need it for rounding*/
A("clr %10") /* %10 = 0*/
A("clr %11") /* %11 = 0*/
A("mul %5,%8") /* r1:r0 = LO(f) * HI(t)*/
A("add %9,r0") /* %9 += LO(LO(f) * HI(t))*/
A("adc %10,r1") /* %10 = HI(LO(f) * HI(t))*/
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%7") /* r1:r0 = HI(f) * LO(t)*/
A("add %9,r0") /* %9 += LO(HI(f) * LO(t))*/
A("adc %10,r1") /* %10 += HI(HI(f) * LO(t)) */
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%8") /* r1:r0 = HI(f) * HI(t)*/
A("add %10,r0") /* %10 += LO(HI(f) * HI(t))*/
A("adc %11,r1") /* %11 += HI(HI(f) * HI(t))*/
A("mov %5,%10") /* %6:%5 = */
A("mov %6,%11") /* f = %10:%11*/
/* umul16x16to16hi(f, f, t); / Range 16 bits : f = t^3 (unsigned) [17]*/
" mul %5,%7" "\n\t" /* r1:r0 = LO(f) * LO(t)*/
" mov %1,r1" "\n\t" /* store MIL(LO(f) * LO(t)) in %1, we need it for rounding*/
" clr %10" "\n\t" /* %10 = 0*/
" clr %11" "\n\t" /* %11 = 0*/
" mul %5,%8" "\n\t" /* r1:r0 = LO(f) * HI(t)*/
" add %1,r0" "\n\t" /* %1 += LO(LO(f) * HI(t))*/
" adc %10,r1" "\n\t" /* %10 = HI(LO(f) * HI(t))*/
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%7" "\n\t" /* r1:r0 = HI(f) * LO(t)*/
" add %1,r0" "\n\t" /* %1 += LO(HI(f) * LO(t))*/
" adc %10,r1" "\n\t" /* %10 += HI(HI(f) * LO(t))*/
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%8" "\n\t" /* r1:r0 = HI(f) * HI(t)*/
" add %10,r0" "\n\t" /* %10 += LO(HI(f) * HI(t))*/
" adc %11,r1" "\n\t" /* %11 += HI(HI(f) * HI(t))*/
" mov %5,%10" "\n\t" /* %6:%5 =*/
" mov %6,%11" "\n\t" /* f = %10:%11*/
A("mul %5,%7") /* r1:r0 = LO(f) * LO(t)*/
A("mov %1,r1") /* store MIL(LO(f) * LO(t)) in %1, we need it for rounding*/
A("clr %10") /* %10 = 0*/
A("clr %11") /* %11 = 0*/
A("mul %5,%8") /* r1:r0 = LO(f) * HI(t)*/
A("add %1,r0") /* %1 += LO(LO(f) * HI(t))*/
A("adc %10,r1") /* %10 = HI(LO(f) * HI(t))*/
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%7") /* r1:r0 = HI(f) * LO(t)*/
A("add %1,r0") /* %1 += LO(HI(f) * LO(t))*/
A("adc %10,r1") /* %10 += HI(HI(f) * LO(t))*/
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%8") /* r1:r0 = HI(f) * HI(t)*/
A("add %10,r0") /* %10 += LO(HI(f) * HI(t))*/
A("adc %11,r1") /* %11 += HI(HI(f) * HI(t))*/
A("mov %5,%10") /* %6:%5 =*/
A("mov %6,%11") /* f = %10:%11*/
/* [15 +17*2] = [49]*/
/* %4:%3:%2 will be acc from now on*/
/* uint24_t acc = bezier_F; / Range 20 bits (unsigned)*/
" clr %9" "\n\t" /* "decimal place we get for free"*/
" lds %2,bezier_F" "\n\t"
" lds %3,bezier_F+1" "\n\t"
" lds %4,bezier_F+2" "\n\t" /* %4:%3:%2 = acc*/
A("clr %9") /* "decimal place we get for free"*/
A("lds %2,bezier_F")
A("lds %3,bezier_F+1")
A("lds %4,bezier_F+2") /* %4:%3:%2 = acc*/
/* if (A_negative) {*/
" lds r0,A_negative" "\n\t"
" or r0,%0" "\n\t" /* Is flag signalling negative? */
" brne 3f" "\n\t" /* If yes, Skip next instruction if A was negative*/
" rjmp 1f" "\n\t" /* Otherwise, jump */
A("lds r0,A_negative")
A("or r0,%0") /* Is flag signalling negative? */
A("brne 3f") /* If yes, Skip next instruction if A was negative*/
A("rjmp 1f") /* Otherwise, jump */
/* uint24_t v; */
/* umul16x24to24hi(v, f, bezier_C); / Range 21bits [29] */
/* acc -= v; */
"3:" "\n\t"
" lds %10, bezier_C" "\n\t" /* %10 = LO(bezier_C)*/
" mul %10,%5" "\n\t" /* r1:r0 = LO(bezier_C) * LO(f)*/
" sub %9,r1" "\n\t"
" sbc %2,%0" "\n\t"
" sbc %3,%0" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= HI(LO(bezier_C) * LO(f))*/
" lds %11, bezier_C+1" "\n\t" /* %11 = MI(bezier_C)*/
" mul %11,%5" "\n\t" /* r1:r0 = MI(bezier_C) * LO(f)*/
" sub %9,r0" "\n\t"
" sbc %2,r1" "\n\t"
" sbc %3,%0" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= MI(bezier_C) * LO(f)*/
" lds %1, bezier_C+2" "\n\t" /* %1 = HI(bezier_C)*/
" mul %1,%5" "\n\t" /* r1:r0 = MI(bezier_C) * LO(f)*/
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= HI(bezier_C) * LO(f) << 8*/
" mul %10,%6" "\n\t" /* r1:r0 = LO(bezier_C) * MI(f)*/
" sub %9,r0" "\n\t"
" sbc %2,r1" "\n\t"
" sbc %3,%0" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= LO(bezier_C) * MI(f)*/
" mul %11,%6" "\n\t" /* r1:r0 = MI(bezier_C) * MI(f)*/
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= MI(bezier_C) * MI(f) << 8*/
" mul %1,%6" "\n\t" /* r1:r0 = HI(bezier_C) * LO(f)*/
" sub %3,r0" "\n\t"
" sbc %4,r1" "\n\t" /* %4:%3:%2:%9 -= HI(bezier_C) * LO(f) << 16*/
L("3")
A("lds %10, bezier_C") /* %10 = LO(bezier_C)*/
A("mul %10,%5") /* r1:r0 = LO(bezier_C) * LO(f)*/
A("sub %9,r1")
A("sbc %2,%0")
A("sbc %3,%0")
A("sbc %4,%0") /* %4:%3:%2:%9 -= HI(LO(bezier_C) * LO(f))*/
A("lds %11, bezier_C+1") /* %11 = MI(bezier_C)*/
A("mul %11,%5") /* r1:r0 = MI(bezier_C) * LO(f)*/
A("sub %9,r0")
A("sbc %2,r1")
A("sbc %3,%0")
A("sbc %4,%0") /* %4:%3:%2:%9 -= MI(bezier_C) * LO(f)*/
A("lds %1, bezier_C+2") /* %1 = HI(bezier_C)*/
A("mul %1,%5") /* r1:r0 = MI(bezier_C) * LO(f)*/
A("sub %2,r0")
A("sbc %3,r1")
A("sbc %4,%0") /* %4:%3:%2:%9 -= HI(bezier_C) * LO(f) << 8*/
A("mul %10,%6") /* r1:r0 = LO(bezier_C) * MI(f)*/
A("sub %9,r0")
A("sbc %2,r1")
A("sbc %3,%0")
A("sbc %4,%0") /* %4:%3:%2:%9 -= LO(bezier_C) * MI(f)*/
A("mul %11,%6") /* r1:r0 = MI(bezier_C) * MI(f)*/
A("sub %2,r0")
A("sbc %3,r1")
A("sbc %4,%0") /* %4:%3:%2:%9 -= MI(bezier_C) * MI(f) << 8*/
A("mul %1,%6") /* r1:r0 = HI(bezier_C) * LO(f)*/
A("sub %3,r0")
A("sbc %4,r1") /* %4:%3:%2:%9 -= HI(bezier_C) * LO(f) << 16*/
/* umul16x16to16hi(f, f, t); / Range 16 bits : f = t^3 (unsigned) [17]*/
" mul %5,%7" "\n\t" /* r1:r0 = LO(f) * LO(t)*/
" mov %1,r1" "\n\t" /* store MIL(LO(f) * LO(t)) in %1, we need it for rounding*/
" clr %10" "\n\t" /* %10 = 0*/
" clr %11" "\n\t" /* %11 = 0*/
" mul %5,%8" "\n\t" /* r1:r0 = LO(f) * HI(t)*/
" add %1,r0" "\n\t" /* %1 += LO(LO(f) * HI(t))*/
" adc %10,r1" "\n\t" /* %10 = HI(LO(f) * HI(t))*/
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%7" "\n\t" /* r1:r0 = HI(f) * LO(t)*/
" add %1,r0" "\n\t" /* %1 += LO(HI(f) * LO(t))*/
" adc %10,r1" "\n\t" /* %10 += HI(HI(f) * LO(t))*/
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%8" "\n\t" /* r1:r0 = HI(f) * HI(t)*/
" add %10,r0" "\n\t" /* %10 += LO(HI(f) * HI(t))*/
" adc %11,r1" "\n\t" /* %11 += HI(HI(f) * HI(t))*/
" mov %5,%10" "\n\t" /* %6:%5 =*/
" mov %6,%11" "\n\t" /* f = %10:%11*/
A("mul %5,%7") /* r1:r0 = LO(f) * LO(t)*/
A("mov %1,r1") /* store MIL(LO(f) * LO(t)) in %1, we need it for rounding*/
A("clr %10") /* %10 = 0*/
A("clr %11") /* %11 = 0*/
A("mul %5,%8") /* r1:r0 = LO(f) * HI(t)*/
A("add %1,r0") /* %1 += LO(LO(f) * HI(t))*/
A("adc %10,r1") /* %10 = HI(LO(f) * HI(t))*/
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%7") /* r1:r0 = HI(f) * LO(t)*/
A("add %1,r0") /* %1 += LO(HI(f) * LO(t))*/
A("adc %10,r1") /* %10 += HI(HI(f) * LO(t))*/
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%8") /* r1:r0 = HI(f) * HI(t)*/
A("add %10,r0") /* %10 += LO(HI(f) * HI(t))*/
A("adc %11,r1") /* %11 += HI(HI(f) * HI(t))*/
A("mov %5,%10") /* %6:%5 =*/
A("mov %6,%11") /* f = %10:%11*/
/* umul16x24to24hi(v, f, bezier_B); / Range 22bits [29]*/
/* acc += v; */
" lds %10, bezier_B" "\n\t" /* %10 = LO(bezier_B)*/
" mul %10,%5" "\n\t" /* r1:r0 = LO(bezier_B) * LO(f)*/
" add %9,r1" "\n\t"
" adc %2,%0" "\n\t"
" adc %3,%0" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += HI(LO(bezier_B) * LO(f))*/
" lds %11, bezier_B+1" "\n\t" /* %11 = MI(bezier_B)*/
" mul %11,%5" "\n\t" /* r1:r0 = MI(bezier_B) * LO(f)*/
" add %9,r0" "\n\t"
" adc %2,r1" "\n\t"
" adc %3,%0" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += MI(bezier_B) * LO(f)*/
" lds %1, bezier_B+2" "\n\t" /* %1 = HI(bezier_B)*/
" mul %1,%5" "\n\t" /* r1:r0 = MI(bezier_B) * LO(f)*/
" add %2,r0" "\n\t"
" adc %3,r1" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += HI(bezier_B) * LO(f) << 8*/
" mul %10,%6" "\n\t" /* r1:r0 = LO(bezier_B) * MI(f)*/
" add %9,r0" "\n\t"
" adc %2,r1" "\n\t"
" adc %3,%0" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += LO(bezier_B) * MI(f)*/
" mul %11,%6" "\n\t" /* r1:r0 = MI(bezier_B) * MI(f)*/
" add %2,r0" "\n\t"
" adc %3,r1" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += MI(bezier_B) * MI(f) << 8*/
" mul %1,%6" "\n\t" /* r1:r0 = HI(bezier_B) * LO(f)*/
" add %3,r0" "\n\t"
" adc %4,r1" "\n\t" /* %4:%3:%2:%9 += HI(bezier_B) * LO(f) << 16*/
A("lds %10, bezier_B") /* %10 = LO(bezier_B)*/
A("mul %10,%5") /* r1:r0 = LO(bezier_B) * LO(f)*/
A("add %9,r1")
A("adc %2,%0")
A("adc %3,%0")
A("adc %4,%0") /* %4:%3:%2:%9 += HI(LO(bezier_B) * LO(f))*/
A("lds %11, bezier_B+1") /* %11 = MI(bezier_B)*/
A("mul %11,%5") /* r1:r0 = MI(bezier_B) * LO(f)*/
A("add %9,r0")
A("adc %2,r1")
A("adc %3,%0")
A("adc %4,%0") /* %4:%3:%2:%9 += MI(bezier_B) * LO(f)*/
A("lds %1, bezier_B+2") /* %1 = HI(bezier_B)*/
A("mul %1,%5") /* r1:r0 = MI(bezier_B) * LO(f)*/
A("add %2,r0")
A("adc %3,r1")
A("adc %4,%0") /* %4:%3:%2:%9 += HI(bezier_B) * LO(f) << 8*/
A("mul %10,%6") /* r1:r0 = LO(bezier_B) * MI(f)*/
A("add %9,r0")
A("adc %2,r1")
A("adc %3,%0")
A("adc %4,%0") /* %4:%3:%2:%9 += LO(bezier_B) * MI(f)*/
A("mul %11,%6") /* r1:r0 = MI(bezier_B) * MI(f)*/
A("add %2,r0")
A("adc %3,r1")
A("adc %4,%0") /* %4:%3:%2:%9 += MI(bezier_B) * MI(f) << 8*/
A("mul %1,%6") /* r1:r0 = HI(bezier_B) * LO(f)*/
A("add %3,r0")
A("adc %4,r1") /* %4:%3:%2:%9 += HI(bezier_B) * LO(f) << 16*/
/* umul16x16to16hi(f, f, t); / Range 16 bits : f = t^5 (unsigned) [17]*/
" mul %5,%7" "\n\t" /* r1:r0 = LO(f) * LO(t)*/
" mov %1,r1" "\n\t" /* store MIL(LO(f) * LO(t)) in %1, we need it for rounding*/
" clr %10" "\n\t" /* %10 = 0*/
" clr %11" "\n\t" /* %11 = 0*/
" mul %5,%8" "\n\t" /* r1:r0 = LO(f) * HI(t)*/
" add %1,r0" "\n\t" /* %1 += LO(LO(f) * HI(t))*/
" adc %10,r1" "\n\t" /* %10 = HI(LO(f) * HI(t))*/
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%7" "\n\t" /* r1:r0 = HI(f) * LO(t)*/
" add %1,r0" "\n\t" /* %1 += LO(HI(f) * LO(t))*/
" adc %10,r1" "\n\t" /* %10 += HI(HI(f) * LO(t))*/
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%8" "\n\t" /* r1:r0 = HI(f) * HI(t)*/
" add %10,r0" "\n\t" /* %10 += LO(HI(f) * HI(t))*/
" adc %11,r1" "\n\t" /* %11 += HI(HI(f) * HI(t))*/
" mov %5,%10" "\n\t" /* %6:%5 =*/
" mov %6,%11" "\n\t" /* f = %10:%11*/
A("mul %5,%7") /* r1:r0 = LO(f) * LO(t)*/
A("mov %1,r1") /* store MIL(LO(f) * LO(t)) in %1, we need it for rounding*/
A("clr %10") /* %10 = 0*/
A("clr %11") /* %11 = 0*/
A("mul %5,%8") /* r1:r0 = LO(f) * HI(t)*/
A("add %1,r0") /* %1 += LO(LO(f) * HI(t))*/
A("adc %10,r1") /* %10 = HI(LO(f) * HI(t))*/
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%7") /* r1:r0 = HI(f) * LO(t)*/
A("add %1,r0") /* %1 += LO(HI(f) * LO(t))*/
A("adc %10,r1") /* %10 += HI(HI(f) * LO(t))*/
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%8") /* r1:r0 = HI(f) * HI(t)*/
A("add %10,r0") /* %10 += LO(HI(f) * HI(t))*/
A("adc %11,r1") /* %11 += HI(HI(f) * HI(t))*/
A("mov %5,%10") /* %6:%5 =*/
A("mov %6,%11") /* f = %10:%11*/
/* umul16x24to24hi(v, f, bezier_A); / Range 21bits [29]*/
/* acc -= v; */
" lds %10, bezier_A" "\n\t" /* %10 = LO(bezier_A)*/
" mul %10,%5" "\n\t" /* r1:r0 = LO(bezier_A) * LO(f)*/
" sub %9,r1" "\n\t"
" sbc %2,%0" "\n\t"
" sbc %3,%0" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= HI(LO(bezier_A) * LO(f))*/
" lds %11, bezier_A+1" "\n\t" /* %11 = MI(bezier_A)*/
" mul %11,%5" "\n\t" /* r1:r0 = MI(bezier_A) * LO(f)*/
" sub %9,r0" "\n\t"
" sbc %2,r1" "\n\t"
" sbc %3,%0" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= MI(bezier_A) * LO(f)*/
" lds %1, bezier_A+2" "\n\t" /* %1 = HI(bezier_A)*/
" mul %1,%5" "\n\t" /* r1:r0 = MI(bezier_A) * LO(f)*/
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= HI(bezier_A) * LO(f) << 8*/
" mul %10,%6" "\n\t" /* r1:r0 = LO(bezier_A) * MI(f)*/
" sub %9,r0" "\n\t"
" sbc %2,r1" "\n\t"
" sbc %3,%0" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= LO(bezier_A) * MI(f)*/
" mul %11,%6" "\n\t" /* r1:r0 = MI(bezier_A) * MI(f)*/
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= MI(bezier_A) * MI(f) << 8*/
" mul %1,%6" "\n\t" /* r1:r0 = HI(bezier_A) * LO(f)*/
" sub %3,r0" "\n\t"
" sbc %4,r1" "\n\t" /* %4:%3:%2:%9 -= HI(bezier_A) * LO(f) << 16*/
" jmp 2f" "\n\t" /* Done!*/
A("lds %10, bezier_A") /* %10 = LO(bezier_A)*/
A("mul %10,%5") /* r1:r0 = LO(bezier_A) * LO(f)*/
A("sub %9,r1")
A("sbc %2,%0")
A("sbc %3,%0")
A("sbc %4,%0") /* %4:%3:%2:%9 -= HI(LO(bezier_A) * LO(f))*/
A("lds %11, bezier_A+1") /* %11 = MI(bezier_A)*/
A("mul %11,%5") /* r1:r0 = MI(bezier_A) * LO(f)*/
A("sub %9,r0")
A("sbc %2,r1")
A("sbc %3,%0")
A("sbc %4,%0") /* %4:%3:%2:%9 -= MI(bezier_A) * LO(f)*/
A("lds %1, bezier_A+2") /* %1 = HI(bezier_A)*/
A("mul %1,%5") /* r1:r0 = MI(bezier_A) * LO(f)*/
A("sub %2,r0")
A("sbc %3,r1")
A("sbc %4,%0") /* %4:%3:%2:%9 -= HI(bezier_A) * LO(f) << 8*/
A("mul %10,%6") /* r1:r0 = LO(bezier_A) * MI(f)*/
A("sub %9,r0")
A("sbc %2,r1")
A("sbc %3,%0")
A("sbc %4,%0") /* %4:%3:%2:%9 -= LO(bezier_A) * MI(f)*/
A("mul %11,%6") /* r1:r0 = MI(bezier_A) * MI(f)*/
A("sub %2,r0")
A("sbc %3,r1")
A("sbc %4,%0") /* %4:%3:%2:%9 -= MI(bezier_A) * MI(f) << 8*/
A("mul %1,%6") /* r1:r0 = HI(bezier_A) * LO(f)*/
A("sub %3,r0")
A("sbc %4,r1") /* %4:%3:%2:%9 -= HI(bezier_A) * LO(f) << 16*/
A("jmp 2f") /* Done!*/
"1:" "\n\t"
L("1")
/* uint24_t v; */
/* umul16x24to24hi(v, f, bezier_C); / Range 21bits [29]*/
/* acc += v; */
" lds %10, bezier_C" "\n\t" /* %10 = LO(bezier_C)*/
" mul %10,%5" "\n\t" /* r1:r0 = LO(bezier_C) * LO(f)*/
" add %9,r1" "\n\t"
" adc %2,%0" "\n\t"
" adc %3,%0" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += HI(LO(bezier_C) * LO(f))*/
" lds %11, bezier_C+1" "\n\t" /* %11 = MI(bezier_C)*/
" mul %11,%5" "\n\t" /* r1:r0 = MI(bezier_C) * LO(f)*/
" add %9,r0" "\n\t"
" adc %2,r1" "\n\t"
" adc %3,%0" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += MI(bezier_C) * LO(f)*/
" lds %1, bezier_C+2" "\n\t" /* %1 = HI(bezier_C)*/
" mul %1,%5" "\n\t" /* r1:r0 = MI(bezier_C) * LO(f)*/
" add %2,r0" "\n\t"
" adc %3,r1" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += HI(bezier_C) * LO(f) << 8*/
" mul %10,%6" "\n\t" /* r1:r0 = LO(bezier_C) * MI(f)*/
" add %9,r0" "\n\t"
" adc %2,r1" "\n\t"
" adc %3,%0" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += LO(bezier_C) * MI(f)*/
" mul %11,%6" "\n\t" /* r1:r0 = MI(bezier_C) * MI(f)*/
" add %2,r0" "\n\t"
" adc %3,r1" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += MI(bezier_C) * MI(f) << 8*/
" mul %1,%6" "\n\t" /* r1:r0 = HI(bezier_C) * LO(f)*/
" add %3,r0" "\n\t"
" adc %4,r1" "\n\t" /* %4:%3:%2:%9 += HI(bezier_C) * LO(f) << 16*/
A("lds %10, bezier_C") /* %10 = LO(bezier_C)*/
A("mul %10,%5") /* r1:r0 = LO(bezier_C) * LO(f)*/
A("add %9,r1")
A("adc %2,%0")
A("adc %3,%0")
A("adc %4,%0") /* %4:%3:%2:%9 += HI(LO(bezier_C) * LO(f))*/
A("lds %11, bezier_C+1") /* %11 = MI(bezier_C)*/
A("mul %11,%5") /* r1:r0 = MI(bezier_C) * LO(f)*/
A("add %9,r0")
A("adc %2,r1")
A("adc %3,%0")
A("adc %4,%0") /* %4:%3:%2:%9 += MI(bezier_C) * LO(f)*/
A("lds %1, bezier_C+2") /* %1 = HI(bezier_C)*/
A("mul %1,%5") /* r1:r0 = MI(bezier_C) * LO(f)*/
A("add %2,r0")
A("adc %3,r1")
A("adc %4,%0") /* %4:%3:%2:%9 += HI(bezier_C) * LO(f) << 8*/
A("mul %10,%6") /* r1:r0 = LO(bezier_C) * MI(f)*/
A("add %9,r0")
A("adc %2,r1")
A("adc %3,%0")
A("adc %4,%0") /* %4:%3:%2:%9 += LO(bezier_C) * MI(f)*/
A("mul %11,%6") /* r1:r0 = MI(bezier_C) * MI(f)*/
A("add %2,r0")
A("adc %3,r1")
A("adc %4,%0") /* %4:%3:%2:%9 += MI(bezier_C) * MI(f) << 8*/
A("mul %1,%6") /* r1:r0 = HI(bezier_C) * LO(f)*/
A("add %3,r0")
A("adc %4,r1") /* %4:%3:%2:%9 += HI(bezier_C) * LO(f) << 16*/
/* umul16x16to16hi(f, f, t); / Range 16 bits : f = t^3 (unsigned) [17]*/
" mul %5,%7" "\n\t" /* r1:r0 = LO(f) * LO(t)*/
" mov %1,r1" "\n\t" /* store MIL(LO(f) * LO(t)) in %1, we need it for rounding*/
" clr %10" "\n\t" /* %10 = 0*/
" clr %11" "\n\t" /* %11 = 0*/
" mul %5,%8" "\n\t" /* r1:r0 = LO(f) * HI(t)*/
" add %1,r0" "\n\t" /* %1 += LO(LO(f) * HI(t))*/
" adc %10,r1" "\n\t" /* %10 = HI(LO(f) * HI(t))*/
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%7" "\n\t" /* r1:r0 = HI(f) * LO(t)*/
" add %1,r0" "\n\t" /* %1 += LO(HI(f) * LO(t))*/
" adc %10,r1" "\n\t" /* %10 += HI(HI(f) * LO(t))*/
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%8" "\n\t" /* r1:r0 = HI(f) * HI(t)*/
" add %10,r0" "\n\t" /* %10 += LO(HI(f) * HI(t))*/
" adc %11,r1" "\n\t" /* %11 += HI(HI(f) * HI(t))*/
" mov %5,%10" "\n\t" /* %6:%5 =*/
" mov %6,%11" "\n\t" /* f = %10:%11*/
A("mul %5,%7") /* r1:r0 = LO(f) * LO(t)*/
A("mov %1,r1") /* store MIL(LO(f) * LO(t)) in %1, we need it for rounding*/
A("clr %10") /* %10 = 0*/
A("clr %11") /* %11 = 0*/
A("mul %5,%8") /* r1:r0 = LO(f) * HI(t)*/
A("add %1,r0") /* %1 += LO(LO(f) * HI(t))*/
A("adc %10,r1") /* %10 = HI(LO(f) * HI(t))*/
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%7") /* r1:r0 = HI(f) * LO(t)*/
A("add %1,r0") /* %1 += LO(HI(f) * LO(t))*/
A("adc %10,r1") /* %10 += HI(HI(f) * LO(t))*/
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%8") /* r1:r0 = HI(f) * HI(t)*/
A("add %10,r0") /* %10 += LO(HI(f) * HI(t))*/
A("adc %11,r1") /* %11 += HI(HI(f) * HI(t))*/
A("mov %5,%10") /* %6:%5 =*/
A("mov %6,%11") /* f = %10:%11*/
/* umul16x24to24hi(v, f, bezier_B); / Range 22bits [29]*/
/* acc -= v;*/
" lds %10, bezier_B" "\n\t" /* %10 = LO(bezier_B)*/
" mul %10,%5" "\n\t" /* r1:r0 = LO(bezier_B) * LO(f)*/
" sub %9,r1" "\n\t"
" sbc %2,%0" "\n\t"
" sbc %3,%0" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= HI(LO(bezier_B) * LO(f))*/
" lds %11, bezier_B+1" "\n\t" /* %11 = MI(bezier_B)*/
" mul %11,%5" "\n\t" /* r1:r0 = MI(bezier_B) * LO(f)*/
" sub %9,r0" "\n\t"
" sbc %2,r1" "\n\t"
" sbc %3,%0" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= MI(bezier_B) * LO(f)*/
" lds %1, bezier_B+2" "\n\t" /* %1 = HI(bezier_B)*/
" mul %1,%5" "\n\t" /* r1:r0 = MI(bezier_B) * LO(f)*/
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= HI(bezier_B) * LO(f) << 8*/
" mul %10,%6" "\n\t" /* r1:r0 = LO(bezier_B) * MI(f)*/
" sub %9,r0" "\n\t"
" sbc %2,r1" "\n\t"
" sbc %3,%0" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= LO(bezier_B) * MI(f)*/
" mul %11,%6" "\n\t" /* r1:r0 = MI(bezier_B) * MI(f)*/
" sub %2,r0" "\n\t"
" sbc %3,r1" "\n\t"
" sbc %4,%0" "\n\t" /* %4:%3:%2:%9 -= MI(bezier_B) * MI(f) << 8*/
" mul %1,%6" "\n\t" /* r1:r0 = HI(bezier_B) * LO(f)*/
" sub %3,r0" "\n\t"
" sbc %4,r1" "\n\t" /* %4:%3:%2:%9 -= HI(bezier_B) * LO(f) << 16*/
A("lds %10, bezier_B") /* %10 = LO(bezier_B)*/
A("mul %10,%5") /* r1:r0 = LO(bezier_B) * LO(f)*/
A("sub %9,r1")
A("sbc %2,%0")
A("sbc %3,%0")
A("sbc %4,%0") /* %4:%3:%2:%9 -= HI(LO(bezier_B) * LO(f))*/
A("lds %11, bezier_B+1") /* %11 = MI(bezier_B)*/
A("mul %11,%5") /* r1:r0 = MI(bezier_B) * LO(f)*/
A("sub %9,r0")
A("sbc %2,r1")
A("sbc %3,%0")
A("sbc %4,%0") /* %4:%3:%2:%9 -= MI(bezier_B) * LO(f)*/
A("lds %1, bezier_B+2") /* %1 = HI(bezier_B)*/
A("mul %1,%5") /* r1:r0 = MI(bezier_B) * LO(f)*/
A("sub %2,r0")
A("sbc %3,r1")
A("sbc %4,%0") /* %4:%3:%2:%9 -= HI(bezier_B) * LO(f) << 8*/
A("mul %10,%6") /* r1:r0 = LO(bezier_B) * MI(f)*/
A("sub %9,r0")
A("sbc %2,r1")
A("sbc %3,%0")
A("sbc %4,%0") /* %4:%3:%2:%9 -= LO(bezier_B) * MI(f)*/
A("mul %11,%6") /* r1:r0 = MI(bezier_B) * MI(f)*/
A("sub %2,r0")
A("sbc %3,r1")
A("sbc %4,%0") /* %4:%3:%2:%9 -= MI(bezier_B) * MI(f) << 8*/
A("mul %1,%6") /* r1:r0 = HI(bezier_B) * LO(f)*/
A("sub %3,r0")
A("sbc %4,r1") /* %4:%3:%2:%9 -= HI(bezier_B) * LO(f) << 16*/
/* umul16x16to16hi(f, f, t); / Range 16 bits : f = t^5 (unsigned) [17]*/
" mul %5,%7" "\n\t" /* r1:r0 = LO(f) * LO(t)*/
" mov %1,r1" "\n\t" /* store MIL(LO(f) * LO(t)) in %1, we need it for rounding*/
" clr %10" "\n\t" /* %10 = 0*/
" clr %11" "\n\t" /* %11 = 0*/
" mul %5,%8" "\n\t" /* r1:r0 = LO(f) * HI(t)*/
" add %1,r0" "\n\t" /* %1 += LO(LO(f) * HI(t))*/
" adc %10,r1" "\n\t" /* %10 = HI(LO(f) * HI(t))*/
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%7" "\n\t" /* r1:r0 = HI(f) * LO(t)*/
" add %1,r0" "\n\t" /* %1 += LO(HI(f) * LO(t))*/
" adc %10,r1" "\n\t" /* %10 += HI(HI(f) * LO(t))*/
" adc %11,%0" "\n\t" /* %11 += carry*/
" mul %6,%8" "\n\t" /* r1:r0 = HI(f) * HI(t)*/
" add %10,r0" "\n\t" /* %10 += LO(HI(f) * HI(t))*/
" adc %11,r1" "\n\t" /* %11 += HI(HI(f) * HI(t))*/
" mov %5,%10" "\n\t" /* %6:%5 =*/
" mov %6,%11" "\n\t" /* f = %10:%11*/
A("mul %5,%7") /* r1:r0 = LO(f) * LO(t)*/
A("mov %1,r1") /* store MIL(LO(f) * LO(t)) in %1, we need it for rounding*/
A("clr %10") /* %10 = 0*/
A("clr %11") /* %11 = 0*/
A("mul %5,%8") /* r1:r0 = LO(f) * HI(t)*/
A("add %1,r0") /* %1 += LO(LO(f) * HI(t))*/
A("adc %10,r1") /* %10 = HI(LO(f) * HI(t))*/
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%7") /* r1:r0 = HI(f) * LO(t)*/
A("add %1,r0") /* %1 += LO(HI(f) * LO(t))*/
A("adc %10,r1") /* %10 += HI(HI(f) * LO(t))*/
A("adc %11,%0") /* %11 += carry*/
A("mul %6,%8") /* r1:r0 = HI(f) * HI(t)*/
A("add %10,r0") /* %10 += LO(HI(f) * HI(t))*/
A("adc %11,r1") /* %11 += HI(HI(f) * HI(t))*/
A("mov %5,%10") /* %6:%5 =*/
A("mov %6,%11") /* f = %10:%11*/
/* umul16x24to24hi(v, f, bezier_A); / Range 21bits [29]*/
/* acc += v; */
" lds %10, bezier_A" "\n\t" /* %10 = LO(bezier_A)*/
" mul %10,%5" "\n\t" /* r1:r0 = LO(bezier_A) * LO(f)*/
" add %9,r1" "\n\t"
" adc %2,%0" "\n\t"
" adc %3,%0" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += HI(LO(bezier_A) * LO(f))*/
" lds %11, bezier_A+1" "\n\t" /* %11 = MI(bezier_A)*/
" mul %11,%5" "\n\t" /* r1:r0 = MI(bezier_A) * LO(f)*/
" add %9,r0" "\n\t"
" adc %2,r1" "\n\t"
" adc %3,%0" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += MI(bezier_A) * LO(f)*/
" lds %1, bezier_A+2" "\n\t" /* %1 = HI(bezier_A)*/
" mul %1,%5" "\n\t" /* r1:r0 = MI(bezier_A) * LO(f)*/
" add %2,r0" "\n\t"
" adc %3,r1" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += HI(bezier_A) * LO(f) << 8*/
" mul %10,%6" "\n\t" /* r1:r0 = LO(bezier_A) * MI(f)*/
" add %9,r0" "\n\t"
" adc %2,r1" "\n\t"
" adc %3,%0" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += LO(bezier_A) * MI(f)*/
" mul %11,%6" "\n\t" /* r1:r0 = MI(bezier_A) * MI(f)*/
" add %2,r0" "\n\t"
" adc %3,r1" "\n\t"
" adc %4,%0" "\n\t" /* %4:%3:%2:%9 += MI(bezier_A) * MI(f) << 8*/
" mul %1,%6" "\n\t" /* r1:r0 = HI(bezier_A) * LO(f)*/
" add %3,r0" "\n\t"
" adc %4,r1" "\n\t" /* %4:%3:%2:%9 += HI(bezier_A) * LO(f) << 16*/
"2:" "\n\t"
A("lds %10, bezier_A") /* %10 = LO(bezier_A)*/
A("mul %10,%5") /* r1:r0 = LO(bezier_A) * LO(f)*/
A("add %9,r1")
A("adc %2,%0")
A("adc %3,%0")
A("adc %4,%0") /* %4:%3:%2:%9 += HI(LO(bezier_A) * LO(f))*/
A("lds %11, bezier_A+1") /* %11 = MI(bezier_A)*/
A("mul %11,%5") /* r1:r0 = MI(bezier_A) * LO(f)*/
A("add %9,r0")
A("adc %2,r1")
A("adc %3,%0")
A("adc %4,%0") /* %4:%3:%2:%9 += MI(bezier_A) * LO(f)*/
A("lds %1, bezier_A+2") /* %1 = HI(bezier_A)*/
A("mul %1,%5") /* r1:r0 = MI(bezier_A) * LO(f)*/
A("add %2,r0")
A("adc %3,r1")
A("adc %4,%0") /* %4:%3:%2:%9 += HI(bezier_A) * LO(f) << 8*/
A("mul %10,%6") /* r1:r0 = LO(bezier_A) * MI(f)*/
A("add %9,r0")
A("adc %2,r1")
A("adc %3,%0")
A("adc %4,%0") /* %4:%3:%2:%9 += LO(bezier_A) * MI(f)*/
A("mul %11,%6") /* r1:r0 = MI(bezier_A) * MI(f)*/
A("add %2,r0")
A("adc %3,r1")
A("adc %4,%0") /* %4:%3:%2:%9 += MI(bezier_A) * MI(f) << 8*/
A("mul %1,%6") /* r1:r0 = HI(bezier_A) * LO(f)*/
A("add %3,r0")
A("adc %4,r1") /* %4:%3:%2:%9 += HI(bezier_A) * LO(f) << 16*/
L("2")
" clr __zero_reg__" /* C runtime expects r1 = __zero_reg__ = 0 */
: "+r"(r0),
"+r"(r1),
@ -1071,20 +1071,20 @@ void Stepper::set_directions() {
register int32_t C = bezier_C;
__asm__ __volatile__(
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
" lsrs %[ahi],%[alo],#1" "\n\t" // a = F << 31 1 cycles
" lsls %[alo],%[alo],#31" "\n\t" // 1 cycles
" umull %[flo],%[fhi],%[fhi],%[t]" "\n\t" // f *= t 5 cycles [fhi:flo=64bits]
" umull %[flo],%[fhi],%[fhi],%[t]" "\n\t" // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
" lsrs %[flo],%[fhi],#1" "\n\t" // 1 cycles [31bits]
" smlal %[alo],%[ahi],%[flo],%[C]" "\n\t" // a+=(f>>33)*C; 5 cycles
" umull %[flo],%[fhi],%[fhi],%[t]" "\n\t" // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
" lsrs %[flo],%[fhi],#1" "\n\t" // 1 cycles [31bits]
" smlal %[alo],%[ahi],%[flo],%[B]" "\n\t" // a+=(f>>33)*B; 5 cycles
" umull %[flo],%[fhi],%[fhi],%[t]" "\n\t" // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
" lsrs %[flo],%[fhi],#1" "\n\t" // f>>=33; 1 cycles [31bits]
" smlal %[alo],%[ahi],%[flo],%[A]" "\n\t" // a+=(f>>33)*A; 5 cycles
" lsrs %[alo],%[ahi],#6" "\n\t" // a>>=38 1 cycles
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
A("lsrs %[ahi],%[alo],#1") // a = F << 31 1 cycles
A("lsls %[alo],%[alo],#31") // 1 cycles
A("umull %[flo],%[fhi],%[fhi],%[t]") // f *= t 5 cycles [fhi:flo=64bits]
A("umull %[flo],%[fhi],%[fhi],%[t]") // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
A("lsrs %[flo],%[fhi],#1") // 1 cycles [31bits]
A("smlal %[alo],%[ahi],%[flo],%[C]") // a+=(f>>33)*C; 5 cycles
A("umull %[flo],%[fhi],%[fhi],%[t]") // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
A("lsrs %[flo],%[fhi],#1") // 1 cycles [31bits]
A("smlal %[alo],%[ahi],%[flo],%[B]") // a+=(f>>33)*B; 5 cycles
A("umull %[flo],%[fhi],%[fhi],%[t]") // f>>=32; f*=t 5 cycles [fhi:flo=64bits]
A("lsrs %[flo],%[fhi],#1") // f>>=33; 1 cycles [31bits]
A("smlal %[alo],%[ahi],%[flo],%[A]") // a+=(f>>33)*A; 5 cycles
A("lsrs %[alo],%[ahi],#6") // a>>=38 1 cycles
: [alo]"+r"( alo ) ,
[flo]"+r"( flo ) ,
[fhi]"+r"( fhi ) ,