FastLED  3.1
fastled_delay.h
Go to the documentation of this file.
1 #ifndef __INC_FL_DELAY_H
2 #define __INC_FL_DELAY_H
3 
4 #include "FastLED.h"
5 
8 
9 FASTLED_NAMESPACE_BEGIN
10 
13 template<int WAIT> class CMinWait {
14  uint16_t mLastMicros;
15 public:
16  CMinWait() { mLastMicros = 0; }
17 
18  void wait() {
19  uint16_t diff;
20  do {
21  diff = (micros() & 0xFFFF) - mLastMicros;
22  } while(diff < WAIT);
23  }
24 
25  void mark() { mLastMicros = micros() & 0xFFFF; }
26 };
27 
28 
30 //
31 // Clock cycle counted delay loop
32 //
34 
35 // Default is now just 'nop', with special case for AVR
36 #if defined(__AVR__)
37 # define NOP __asm__ __volatile__ ("cp r0,r0\n");
38 # define NOP2 __asm__ __volatile__ ("rjmp .+0");
39 #else
40 # define NOP __asm__ __volatile__ ("nop\n");
41 # define NOP2 __asm__ __volatile__ ("nop\n\t nop\n");
42 #endif
43 
44 // predeclaration to not upset the compiler
45 template<int CYCLES> inline void delaycycles();
46 template<int CYCLES> inline void delaycycles_min1() {
47  delaycycles<1>();
48  delaycycles<CYCLES-1>();
49 }
50 
51 
52 // TODO: ARM version of _delaycycles_
53 
54 // usable definition
55 #if defined(FASTLED_AVR)
56 // worker template - this will nop for LOOP * 3 + PAD cycles total
57 template<int LOOP, int PAD> inline void _delaycycles_AVR() {
58  delaycycles<PAD>();
59  // the loop below is 3 cycles * LOOP. the LDI is one cycle,
60  // the DEC is 1 cycle, the BRNE is 2 cycles if looping back and
61  // 1 if not (the LDI balances out the BRNE being 1 cycle on exit)
62  __asm__ __volatile__ (
63  " LDI R16, %0\n"
64  "L_%=: DEC R16\n"
65  " BRNE L_%=\n"
66  : /* no outputs */
67  : "M" (LOOP)
68  : "r16"
69  );
70 }
71 
72 template<int CYCLES> __attribute__((always_inline)) inline void delaycycles() {
73  _delaycycles_AVR<CYCLES / 3, CYCLES % 3>();
74 }
75 #else
76 // template<int LOOP, int PAD> inline void _delaycycles_ARM() {
77 // delaycycles<PAD>();
78 // // the loop below is 3 cycles * LOOP. the LDI is one cycle,
79 // // the DEC is 1 cycle, the BRNE is 2 cycles if looping back and
80 // // 1 if not (the LDI balances out the BRNE being 1 cycle on exit)
81 // __asm__ __volatile__ (
82 // " mov.w r9, %0\n"
83 // "L_%=: subs.w r9, r9, #1\n"
84 // " bne.n L_%=\n"
85 // : /* no outputs */
86 // : "M" (LOOP)
87 // : "r9"
88 // );
89 // }
90 
91 
92 template<int CYCLES> __attribute__((always_inline)) inline void delaycycles() {
93  // _delaycycles_ARM<CYCLES / 3, CYCLES % 3>();
94  NOP; delaycycles<CYCLES-1>();
95 }
96 #endif
97 
98 // pre-instantiations for values small enough to not need the loop, as well as sanity holders
99 // for some negative values.
100 template<> __attribute__((always_inline)) inline void delaycycles<-10>() {}
101 template<> __attribute__((always_inline)) inline void delaycycles<-9>() {}
102 template<> __attribute__((always_inline)) inline void delaycycles<-8>() {}
103 template<> __attribute__((always_inline)) inline void delaycycles<-7>() {}
104 template<> __attribute__((always_inline)) inline void delaycycles<-6>() {}
105 template<> __attribute__((always_inline)) inline void delaycycles<-5>() {}
106 template<> __attribute__((always_inline)) inline void delaycycles<-4>() {}
107 template<> __attribute__((always_inline)) inline void delaycycles<-3>() {}
108 template<> __attribute__((always_inline)) inline void delaycycles<-2>() {}
109 template<> __attribute__((always_inline)) inline void delaycycles<-1>() {}
110 template<> __attribute__((always_inline)) inline void delaycycles<0>() {}
111 template<> __attribute__((always_inline)) inline void delaycycles<1>() {NOP;}
112 template<> __attribute__((always_inline)) inline void delaycycles<2>() {NOP2;}
113 template<> __attribute__((always_inline)) inline void delaycycles<3>() {NOP;NOP2;}
114 template<> __attribute__((always_inline)) inline void delaycycles<4>() {NOP2;NOP2;}
115 template<> __attribute__((always_inline)) inline void delaycycles<5>() {NOP2;NOP2;NOP;}
116 
117 // Some timing related macros/definitions
118 
119 // Macro to convert from nano-seconds to clocks and clocks to nano-seconds
120 // #define NS(_NS) (_NS / (1000 / (F_CPU / 1000000L)))
121 #define F_CPU_MHZ (F_CPU / 1000000L)
122 
123 // #define NS(_NS) ( (_NS * (F_CPU / 1000000L))) / 1000
124 #define NS(_NS) (((_NS * F_CPU_MHZ) + 999) / 1000)
125 #define CLKS_TO_MICROS(_CLKS) ((long)(_CLKS)) / (F_CPU / 1000000L)
126 
127 // Macro for making sure there's enough time available
128 #define NO_TIME(A, B, C) (NS(A) < 3 || NS(B) < 3 || NS(C) < 6)
129 
130 FASTLED_NAMESPACE_END
131 
132 #endif
Class to ensure that a minimum amount of time has kicked since the last time run - and delay if not e...
Definition: fastled_delay.h:13
central include file for FastLED, defines the CFastLED class/object
__attribute__((always_inline)) inline void delaycycles()
Do an 8byte by 8bit rotation.
Definition: fastled_delay.h:72