FastLED 3.9.15
Loading...
Searching...
No Matches
fastled_delay.h
Go to the documentation of this file.
1#pragma once
2
3#ifndef __INC_FL_DELAY_H
4#define __INC_FL_DELAY_H
5
6#include "FastLED.h"
7#include "fl/types.h"
8#include "fl/force_inline.h"
9
12
14
15
16#if (!defined(NO_MINIMUM_WAIT) || (NO_MINIMUM_WAIT==0))
17
20template<int WAIT> class CMinWait {
22 uint16_t mLastMicros;
23
24public:
27
29 void wait() {
30 uint16_t diff;
31 do {
32 diff = (micros() & 0xFFFF) - mLastMicros;
33 } while(diff < WAIT);
34 }
35
37 void mark() { mLastMicros = micros() & 0xFFFF; }
38};
39
40#else
41
42// if you keep your own FPS (and therefore don't call show() too quickly for pixels to latch), you may not want a minimum wait.
43template<int WAIT> class CMinWait {
44public:
45 CMinWait() { }
46 void wait() { }
47 void mark() {}
48};
49
50#endif
51
52
58
59// Default is now just 'nop', with special case for AVR
60
61// ESP32 core has it's own definition of NOP, so undef it first
62#ifdef ESP32
63#undef NOP
64#undef NOP2
65#endif
66
67#if defined(__AVR__)
68# define FL_NOP __asm__ __volatile__ ("cp r0,r0\n");
69# define FL_NOP2 __asm__ __volatile__ ("rjmp .+0");
70#else
72# define FL_NOP __asm__ __volatile__ ("nop\n");
74# define FL_NOP2 __asm__ __volatile__ ("nop\n\t nop\n");
75#endif
76
77// predeclaration to not upset the compiler
78
79
83template<fl::cycle_t CYCLES> inline void delaycycles();
84
87template<fl::cycle_t CYCLES> inline void delaycycles_min1() {
89 delaycycles<CYCLES-1>();
90}
91
92
93// TODO: ARM version of _delaycycles_
94
95// usable definition
96#if defined(FASTLED_AVR)
97// worker template - this will nop for LOOP * 3 + PAD cycles total
98template<int LOOP, fl::cycle_t PAD> inline void _delaycycles_AVR() {
100 // the loop below is 3 cycles * LOOP. the LDI is one cycle,
101 // the DEC is 1 cycle, the BRNE is 2 cycles if looping back and
102 // 1 if not (the LDI balances out the BRNE being 1 cycle on exit)
103 __asm__ __volatile__ (
104 " LDI R16, %0\n"
105 "L_%=: DEC R16\n"
106 " BRNE L_%=\n"
107 : /* no outputs */
108 : "M" (LOOP)
109 : "r16"
110 );
111}
112
113template<fl::cycle_t CYCLES> FASTLED_FORCE_INLINE void delaycycles() {
114 _delaycycles_AVR<CYCLES / 3, CYCLES % 3>();
115}
116
117
118
119#else
120// template<int LOOP, fl::cycle_t PAD> inline void _delaycycles_ARM() {
121// delaycycles<PAD>();
122// // the loop below is 3 cycles * LOOP. the LDI is one cycle,
123// // the DEC is 1 cycle, the BRNE is 2 cycles if looping back and
124// // 1 if not (the LDI balances out the BRNE being 1 cycle on exit)
125// __asm__ __volatile__ (
126// " mov.w r9, %0\n"
127// "L_%=: subs.w r9, r9, #1\n"
128// " bne.n L_%=\n"
129// : /* no outputs */
130// : "M" (LOOP)
131// : "r9"
132// );
133// }
134
135
136template<fl::cycle_t CYCLES> FASTLED_FORCE_INLINE void delaycycles() {
137 // _delaycycles_ARM<CYCLES / 3, CYCLES % 3>();
138 FL_NOP; delaycycles<CYCLES-1>();
139}
140
141
142
143
144#endif
145
146// pre-instantiations for values small enough to not need the loop, as well as sanity holders
147// for some negative values.
148
149// These are hidden from Doxygen because they match the expected behavior of the class.
151template<> FASTLED_FORCE_INLINE void delaycycles<-10>() {}
152template<> FASTLED_FORCE_INLINE void delaycycles<-9>() {}
153template<> FASTLED_FORCE_INLINE void delaycycles<-8>() {}
154template<> FASTLED_FORCE_INLINE void delaycycles<-7>() {}
155template<> FASTLED_FORCE_INLINE void delaycycles<-6>() {}
156template<> FASTLED_FORCE_INLINE void delaycycles<-5>() {}
157template<> FASTLED_FORCE_INLINE void delaycycles<-4>() {}
158template<> FASTLED_FORCE_INLINE void delaycycles<-3>() {}
159template<> FASTLED_FORCE_INLINE void delaycycles<-2>() {}
160template<> FASTLED_FORCE_INLINE void delaycycles<-1>() {}
161template<> FASTLED_FORCE_INLINE void delaycycles<0>() {}
162template<> FASTLED_FORCE_INLINE void delaycycles<1>() {FL_NOP;}
167#if defined(ESP32)
169 // specialization for a gigantic amount of cycles, apparently this is needed
170 // or esp32 will blow the stack with cycles = 4294966398.
171 const uint32_t termination = 4294966398 / 10;
172 const uint32_t remainder = 4294966398 % 10;
173 for (uint32_t i = 0; i < termination; i++) {
176 }
177
178 // remainder
179 switch (remainder) {
180 case 9: FL_NOP;
181 case 8: FL_NOP;
182 case 7: FL_NOP;
183 case 6: FL_NOP;
184 case 5: FL_NOP;
185 case 4: FL_NOP;
186 case 3: FL_NOP;
187 case 2: FL_NOP;
188 case 1: FL_NOP;
189 }
190}
191#endif
193
195
196
199
200// Macro to convert from nano-seconds to clocks and clocks to nano-seconds
201// #define NS(_NS) (_NS / (1000 / (F_CPU / 1000000L)))
202
204#define F_CPU_MHZ (F_CPU / 1000000L)
205
206// #define NS(_NS) ( (_NS * (F_CPU / 1000000L))) / 1000
207
209#define NS(_NS) (((_NS * F_CPU_MHZ) + 999) / 1000)
211#define CLKS_TO_MICROS(_CLKS) ((long)(_CLKS)) / (F_CPU / 1000000L)
212
214#define NO_TIME(A, B, C) (NS(A) < 3 || NS(B) < 3 || NS(C) < 6)
215
217
219
220#endif
central include file for FastLED, defines the CFastLED class/object
CMinWait()
Constructor.
uint16_t mLastMicros
Timestamp of the last time this was run, in microseconds.
void mark()
Reset the timestamp that marks the start of the wait period.
void wait()
Blocking delay until WAIT time since mark() has passed.
Class to ensure that a minimum amount of time has kicked since the last time run - and delay if not e...
#define FL_NOP2
Double no operation ("no-op") instruction for delay.
void delaycycles_min1()
A variant of delaycycles that will always delay at least one cycle.
void delaycycles()
Delay N clock cycles.
#define FL_NOP
Single no operation ("no-op") instruction for delay.
#define FASTLED_FORCE_INLINE
Definition force_inline.h:6
#define FASTLED_NAMESPACE_END
Definition namespace.h:23