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