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