FastLED 3.9.15
Loading...
Searching...
No Matches
lib8tion.cpp.hpp
Go to the documentation of this file.
1
4
5#include "fl/stl/stdint.h"
6#include "platforms/is_platform.h"
7
9#define FASTLED_INTERNAL
10
11
12#include "fl/system/fastled.h"
13
14
15
17#define RAND16_SEED 1337
19
20
21
22
23// memset8, memcpy8, memmove8:
24// optimized avr replacements for the standard "C" library
25// routines memset, memcpy, and memmove.
26//
27// There are two techniques that make these routines
28// faster than the standard avr-libc routines.
29// First, the loops are unrolled 2X, meaning that
30// the average loop overhead is cut in half.
31// And second, the compare-and-branch at the bottom
32// of each loop decrements the low byte of the
33// counter, and if the carry is clear, it branches
34// back up immediately. Only if the low byte math
35// causes carry do we bother to decrement the high
36// byte and check that result for carry as well.
37// Results for a 100-byte buffer are 20-40% faster
38// than standard avr-libc, at a cost of a few extra
39// bytes of code.
40
41#if defined(FL_IS_AVR)
42extern "C" {
43//__attribute__ ((noinline))
44void * memset8 ( void * ptr, fl::u8 val, fl::u16 num )
45{
46 asm volatile(
47 " movw r26, %[ptr] \n\t"
48 " sbrs %A[num], 0 \n\t"
49 " rjmp Lseteven_%= \n\t"
50 " rjmp Lsetodd_%= \n\t"
51 "Lsetloop_%=: \n\t"
52 " st X+, %[val] \n\t"
53 "Lsetodd_%=: \n\t"
54 " st X+, %[val] \n\t"
55 "Lseteven_%=: \n\t"
56 " subi %A[num], 2 \n\t"
57 " brcc Lsetloop_%= \n\t"
58 " sbci %B[num], 0 \n\t"
59 " brcc Lsetloop_%= \n\t"
60 : [num] "+r" (num)
61 : [ptr] "r" (ptr),
62 [val] "r" (val)
63 : "memory"
64 );
65 return ptr;
66}
67
68
69
70//__attribute__ ((noinline))
71void * memcpy8 ( void * dst, const void* src, fl::u16 num )
72{
73 asm volatile(
74 " movw r30, %[src] \n\t"
75 " movw r26, %[dst] \n\t"
76 " sbrs %A[num], 0 \n\t"
77 " rjmp Lcpyeven_%= \n\t"
78 " rjmp Lcpyodd_%= \n\t"
79 "Lcpyloop_%=: \n\t"
80 " ld __tmp_reg__, Z+ \n\t"
81 " st X+, __tmp_reg__ \n\t"
82 "Lcpyodd_%=: \n\t"
83 " ld __tmp_reg__, Z+ \n\t"
84 " st X+, __tmp_reg__ \n\t"
85 "Lcpyeven_%=: \n\t"
86 " subi %A[num], 2 \n\t"
87 " brcc Lcpyloop_%= \n\t"
88 " sbci %B[num], 0 \n\t"
89 " brcc Lcpyloop_%= \n\t"
90 : [num] "+r" (num)
91 : [src] "r" (src),
92 [dst] "r" (dst)
93 : "memory"
94 );
95 return dst;
96}
97
98//__attribute__ ((noinline))
99void * memmove8 ( void * dst, const void* src, fl::u16 num )
100{
101 if( src > dst) {
102 // if src > dst then we can use the forward-stepping memcpy8
103 return memcpy8( dst, src, num);
104 } else {
105 // if src < dst then we have to step backward:
106 dst = (char*)dst + num;
107 src = (char*)src + num;
108 asm volatile(
109 " movw r30, %[src] \n\t"
110 " movw r26, %[dst] \n\t"
111 " sbrs %A[num], 0 \n\t"
112 " rjmp Lmoveven_%= \n\t"
113 " rjmp Lmovodd_%= \n\t"
114 "Lmovloop_%=: \n\t"
115 " ld __tmp_reg__, -Z \n\t"
116 " st -X, __tmp_reg__ \n\t"
117 "Lmovodd_%=: \n\t"
118 " ld __tmp_reg__, -Z \n\t"
119 " st -X, __tmp_reg__ \n\t"
120 "Lmoveven_%=: \n\t"
121 " subi %A[num], 2 \n\t"
122 " brcc Lmovloop_%= \n\t"
123 " sbci %B[num], 0 \n\t"
124 " brcc Lmovloop_%= \n\t"
125 : [num] "+r" (num)
126 : [src] "r" (src),
127 [dst] "r" (dst)
128 : "memory"
129 );
130 return dst;
131 }
132}
133
134
135} /* end extern "C" */
136
137#endif /* FL_IS_AVR */
138
139
140
141
142#if 0
143// TEST / VERIFICATION CODE ONLY BELOW THIS POINT
144// IWYU pragma: begin_keep
145#include "fl/system/arduino.h"
146// IWYU pragma: end_keep // ok include
147#include "lib8tion.h"
148
149void test1abs( fl::i8 i)
150{
151 Serial.print("abs("); Serial.print(i); Serial.print(") = ");
152 fl::i8 j = abs8(i);
153 Serial.print(j); Serial.println(" ");
154}
155
156void testabs()
157{
158 delay(5000);
159 for( fl::i8 q = -128; q != 127; ++q) {
160 test1abs(q);
161 }
162 for(;;){};
163}
164
165
166void testmul8()
167{
168 delay(5000);
169 byte r, c;
170
171 Serial.println("mul8:");
172 for( r = 0; r <= 20; r += 1) {
173 Serial.print(r); Serial.print(" : ");
174 for( c = 0; c <= 20; c += 1) {
175 byte t;
176 t = fl::mul8( r, c);
177 Serial.print(t); Serial.print(' ');
178 }
179 Serial.println(' ');
180 }
181 Serial.println("done.");
182 for(;;){};
183}
184
185
186void testscale8()
187{
188 delay(5000);
189 byte r, c;
190
191 Serial.println("scale8:");
192 for( r = 0; r <= 240; r += 10) {
193 Serial.print(r); Serial.print(" : ");
194 for( c = 0; c <= 240; c += 10) {
195 byte t;
196 t = fl::scale8( r, c);
197 Serial.print(t); Serial.print(' ');
198 }
199 Serial.println(' ');
200 }
201
202 Serial.println(' ');
203 Serial.println("scale8_video:");
204
205 for( r = 0; r <= 100; r += 4) {
206 Serial.print(r); Serial.print(" : ");
207 for( c = 0; c <= 100; c += 4) {
208 byte t;
209 t = fl::scale8_video( r, c);
210 Serial.print(t); Serial.print(' ');
211 }
212 Serial.println(' ');
213 }
214
215 Serial.println("done.");
216 for(;;){};
217}
218
219
220
221void testqadd8()
222{
223 delay(5000);
224 byte r, c;
225 for( r = 0; r <= 240; r += 10) {
226 Serial.print(r); Serial.print(" : ");
227 for( c = 0; c <= 240; c += 10) {
228 byte t;
229 t = fl::qadd8( r, c);
230 Serial.print(t); Serial.print(' ');
231 }
232 Serial.println(' ');
233 }
234 Serial.println("done.");
235 for(;;){};
236}
237
238void testnscale8x3()
239{
240 delay(5000);
241 byte r, g, b, sc;
242 for( byte z = 0; z < 10; ++z) {
243 r = random8(); g = random8(); b = random8(); sc = random8();
244
245 Serial.print("nscale8x3_video( ");
246 Serial.print(r); Serial.print(", ");
247 Serial.print(g); Serial.print(", ");
248 Serial.print(b); Serial.print(", ");
249 Serial.print(sc); Serial.print(") = [ ");
250
251 nscale8x3_video( r, g, b, sc);
252
253 Serial.print(r); Serial.print(", ");
254 Serial.print(g); Serial.print(", ");
255 Serial.print(b); Serial.print("]");
256
257 Serial.println(' ');
258 }
259 Serial.println("done.");
260 for(;;){};
261}
262
263#endif
uint32_t z[NUM_LAYERS]
Definition Fire2023.h:93
static uint32_t t
Definition Luminova.h:55
Internal FastLED header for implementation files.
void * memcpy8(void *dst, const void *src, fl::u16 num) FL_NO_INLINE
Faster alternative to memcpy() on AVR.
void * memmove8(void *dst, const void *src, fl::u16 num)
Faster alternative to memmove() on AVR.
void * memset8(void *ptr, fl::u8 value, fl::u16 num) FL_NO_INLINE
Faster alternative to memset() on AVR.
fl::u16 rand16seed
Seed for the random number generator functions.
LIB8STATIC fl::u8 random8() FL_NOEXCEPT
Generate an 8-bit random number.
Definition random8.h:53
#define RAND16_SEED
Seed for the random number generator functions.
Fast, efficient 8-bit math functions specifically designed for high-performance LED programming.
unsigned char u8
Definition stdint.h:131
void delay(u32 ms, bool run_async=true) FL_NOEXCEPT
Public delay wrapper that keeps bare Arduino delay() preferred after using fl::delay; while still all...
Definition delay.h:98
signed char i8
Definition stdint.h:130
#define Serial
Definition serial.h:304