diff options
-rw-r--r-- | fastled_delay.h | 119 | ||||
-rw-r--r-- | platforms/arm/k20/fastled_arm_k20.h | 2 | ||||
-rw-r--r-- | platforms/arm/k26/fastled_arm_k26.h | 2 | ||||
-rw-r--r-- | platforms/arm/nrf51/fastled_arm_nrf51.h | 2 | ||||
-rw-r--r-- | platforms/arm/sam/fastled_arm_sam.h | 2 | ||||
-rw-r--r-- | platforms/arm/stm32/fastled_arm_stm32.h | 2 | ||||
-rw-r--r-- | platforms/avr/fastled_avr.h | 2 |
7 files changed, 125 insertions, 6 deletions
diff --git a/fastled_delay.h b/fastled_delay.h new file mode 100644 index 00000000..015bc1a1 --- /dev/null +++ b/fastled_delay.h @@ -0,0 +1,119 @@ +#ifndef __INC_FL_DELAY_H +#define __INC_FL_DELAY_H + +FASTLED_NAMESPACE_BEGIN + +/// Class to ensure that a minimum amount of time has kicked since the last time run - and delay if not enough time has passed yet +/// this should make sure that chipsets that have +template<int WAIT> class CMinWait { + uint16_t mLastMicros; +public: + CMinWait() { mLastMicros = 0; } + + void wait() { + uint16_t diff; + do { + diff = (micros() & 0xFFFF) - mLastMicros; + } while(diff < WAIT); + } + + void mark() { mLastMicros = micros() & 0xFFFF; } +}; + + +//////////////////////////////////////////////////////////////////////////////////////////// +// +// Clock cycle counted delay loop +// +//////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(__arm__) +# define NOP __asm__ __volatile__ ("nop\n"); +# define NOP2 __asm__ __volatile__ ("nop\n\tnop"); +#else +# define NOP __asm__ __volatile__ ("cp r0,r0\n"); +# define NOP2 __asm__ __volatile__ ("rjmp .+0"); +#endif + +// predeclaration to not upset the compiler +template<int CYCLES> inline void delaycycles(); + +// TODO: ARM version of _delaycycles_ + +// usable definition +#if defined(FASTLED_AVR) +// worker template - this will nop for LOOP * 3 + PAD cycles total +template<int LOOP, int PAD> inline void _delaycycles_AVR() { + delaycycles<PAD>(); + // the loop below is 3 cycles * LOOP. the LDI is one cycle, + // the DEC is 1 cycle, the BRNE is 2 cycles if looping back and + // 1 if not (the LDI balances out the BRNE being 1 cycle on exit) + __asm__ __volatile__ ( + " LDI R16, %0\n" + "L_%=: DEC R16\n" + " BRNE L_%=\n" + : /* no outputs */ + : "M" (LOOP) + : "r16" + ); +} + +template<int CYCLES> __attribute__((always_inline)) inline void delaycycles() { + _delaycycles_AVR<CYCLES / 3, CYCLES % 3>(); +} +#else +// template<int LOOP, int PAD> inline void _delaycycles_ARM() { +// delaycycles<PAD>(); +// // the loop below is 3 cycles * LOOP. the LDI is one cycle, +// // the DEC is 1 cycle, the BRNE is 2 cycles if looping back and +// // 1 if not (the LDI balances out the BRNE being 1 cycle on exit) +// __asm__ __volatile__ ( +// " mov.w r9, %0\n" +// "L_%=: subs.w r9, r9, #1\n" +// " bne.n L_%=\n" +// : /* no outputs */ +// : "M" (LOOP) +// : "r9" +// ); +// } + + +template<int CYCLES> __attribute__((always_inline)) inline void delaycycles() { + // _delaycycles_ARM<CYCLES / 3, CYCLES % 3>(); + NOP; delaycycles<CYCLES-1>(); +} +#endif + +// pre-instantiations for values small enough to not need the loop, as well as sanity holders +// for some negative values. +template<> __attribute__((always_inline)) inline void delaycycles<-6>() {} +template<> __attribute__((always_inline)) inline void delaycycles<-5>() {} +template<> __attribute__((always_inline)) inline void delaycycles<-4>() {} +template<> __attribute__((always_inline)) inline void delaycycles<-3>() {} +template<> __attribute__((always_inline)) inline void delaycycles<-2>() {} +template<> __attribute__((always_inline)) inline void delaycycles<-1>() {} +template<> __attribute__((always_inline)) inline void delaycycles<0>() {} +template<> __attribute__((always_inline)) inline void delaycycles<1>() {NOP;} +template<> __attribute__((always_inline)) inline void delaycycles<2>() {NOP2;} +template<> __attribute__((always_inline)) inline void delaycycles<3>() {NOP;NOP2;} +template<> __attribute__((always_inline)) inline void delaycycles<4>() {NOP2;NOP2;} +template<> __attribute__((always_inline)) inline void delaycycles<5>() {NOP2;NOP2;NOP;} + +// Some timing related macros/definitions + +// Macro to convert from nano-seconds to clocks and clocks to nano-seconds +// #define NS(_NS) (_NS / (1000 / (F_CPU / 1000000L))) +#if 1 || (F_CPU < 96000000) +#define NS(_NS) ( (_NS * (F_CPU / 1000000L))) / 1000 +#define CLKS_TO_MICROS(_CLKS) ((long)(_CLKS)) / (F_CPU / 1000000L) +#else +#define NS(_NS) ( (_NS * (F_CPU / 2000000L))) / 1000 +#define CLKS_TO_MICROS(_CLKS) ((long)(_CLKS)) / (F_CPU / 2000000L) +#endif + +// Macro for making sure there's enough time available +#define NO_TIME(A, B, C) (NS(A) < 3 || NS(B) < 3 || NS(C) < 6) + +FASTLED_NAMESPACE_END + +#endif diff --git a/platforms/arm/k20/fastled_arm_k20.h b/platforms/arm/k20/fastled_arm_k20.h index 48565ec5..7220aef2 100644 --- a/platforms/arm/k20/fastled_arm_k20.h +++ b/platforms/arm/k20/fastled_arm_k20.h @@ -3,7 +3,7 @@ // Include the k20 headers #include "bitswap.h" -#include "delay.h" +#include "fastled_delay.h" #include "fastpin_arm_k20.h" #include "fastspi_arm_k20.h" #include "octows2811_controller.h" diff --git a/platforms/arm/k26/fastled_arm_k26.h b/platforms/arm/k26/fastled_arm_k26.h index 74b34df6..382531bf 100644 --- a/platforms/arm/k26/fastled_arm_k26.h +++ b/platforms/arm/k26/fastled_arm_k26.h @@ -2,7 +2,7 @@ #define __INC_FASTLED_ARM_K26_H // Include the k20 headers -#include "delay.h" +#include "fastled_delay.h" #include "fastpin_arm_k26.h" #include "fastspi_arm_k26.h" #include "clockless_arm_k26.h" diff --git a/platforms/arm/nrf51/fastled_arm_nrf51.h b/platforms/arm/nrf51/fastled_arm_nrf51.h index 617f1bfb..bfdefc34 100644 --- a/platforms/arm/nrf51/fastled_arm_nrf51.h +++ b/platforms/arm/nrf51/fastled_arm_nrf51.h @@ -3,7 +3,7 @@ // Include the k20 headers #include "bitswap.h" -#include "delay.h" +#include "fastled_delay.h" #include "fastpin_arm_nrf51.h" #include "fastspi_arm_nrf51.h" #include "clockless_arm_nrf51.h" diff --git a/platforms/arm/sam/fastled_arm_sam.h b/platforms/arm/sam/fastled_arm_sam.h index 51e2f37c..fd61c14c 100644 --- a/platforms/arm/sam/fastled_arm_sam.h +++ b/platforms/arm/sam/fastled_arm_sam.h @@ -2,7 +2,7 @@ #define __INC_FASTLED_ARM_SAM_H // Include the sam headers -#include "delay.h" +#include "fastled_delay.h" #include "fastpin_arm_sam.h" #include "fastspi_arm_sam.h" #include "clockless_arm_sam.h" diff --git a/platforms/arm/stm32/fastled_arm_stm32.h b/platforms/arm/stm32/fastled_arm_stm32.h index c61c3e0d..e790bfec 100644 --- a/platforms/arm/stm32/fastled_arm_stm32.h +++ b/platforms/arm/stm32/fastled_arm_stm32.h @@ -2,7 +2,7 @@ #define __INC_FASTLED_ARM_SAM_H // Include the sam headers -#include "delay.h" +#include "fastled_delay.h" #include "fastpin_arm_stm32.h" // #include "fastspi_arm_stm32.h" #include "clockless_arm_stm32.h" diff --git a/platforms/avr/fastled_avr.h b/platforms/avr/fastled_avr.h index 4c9b842e..f95c92f4 100644 --- a/platforms/avr/fastled_avr.h +++ b/platforms/avr/fastled_avr.h @@ -1,7 +1,7 @@ #ifndef __INC_FASTLED_AVR_H #define __INC_FASTLED_AVR_H -#include "delay.h" +#include "fastled_delay.h" #include "fastpin_avr.h" #include "fastspi_avr.h" #include "clockless_trinket.h" |