3232#include "tick.h"
3333
3434#ifdef SAMD51
35- static inline void delay_cycles ( uint8_t cycles ) {
36- uint32_t start = SysTick -> VAL ;
37- uint32_t stop = start - cycles ;
38- if ( start < cycles ) {
39- stop = 0xffffff + start - cycles ;
40- while ( SysTick -> VAL < start || SysTick -> VAL > stop ) {}
41- } else {
42- // Make sure the systick value is between start and stop in case it
43- // wraps around before we read its value less than stop.
44- while ( SysTick -> VAL > stop && SysTick -> VAL <= start ) {}
35+ // This magical macro makes sure the delay isn't optimized out and is the
36+ // minimal three instructions.
37+ #define delay_cycles ( cycles ) \
38+ { \
39+ uint32_t t; \
40+ asm volatile ( \
41+ "movs %[t], %[c]\n\t" \
42+ "loop%=:\n\t" \
43+ "subs %[t], #1\n\t" \
44+ "bne.n loop%=" : [t] "=r"(t) : [c] "I" (cycles)); \
4545 }
46- }
4746#endif
4847
4948uint64_t next_start_tick_ms = 0 ;
@@ -88,7 +87,7 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout,
8887 asm("nop; nop;" );
8988 #endif
9089 #ifdef SAMD51
91- delay_cycles (18 );
90+ delay_cycles (3 );
9291 #endif
9392 if (p & bitMask ) {
9493 // This is the high delay unique to a one bit.
@@ -97,7 +96,7 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout,
9796 asm("nop; nop; nop; nop; nop; nop; nop;" );
9897 #endif
9998 #ifdef SAMD51
100- delay_cycles (25 );
99+ delay_cycles (11 );
101100 #endif
102101 * clr = pinMask ;
103102 } else {
@@ -108,7 +107,7 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout,
108107 asm("nop; nop;" );
109108 #endif
110109 #ifdef SAMD51
111- delay_cycles (25 );
110+ delay_cycles (3 );
112111 #endif
113112 }
114113 if ((bitMask >>= 1 ) != 0 ) {
@@ -119,7 +118,7 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout,
119118 asm("nop; nop; nop; nop; nop;" );
120119 #endif
121120 #ifdef SAMD51
122- delay_cycles (44 );
121+ delay_cycles (20 );
123122 #endif
124123 } else {
125124 if (ptr >= end ) break ;
@@ -130,7 +129,7 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout,
130129 // above operations take.
131130 // For the SK6812 its 0.6us +- 0.15us
132131 #ifdef SAMD51
133- delay_cycles (50 );
132+ delay_cycles (15 );
134133 #endif
135134 }
136135 }
0 commit comments