FastLED 3.9.15
Loading...
Searching...
No Matches
trig8.h
Go to the documentation of this file.
1#ifndef __INC_LIB8TION_TRIG_H
2#define __INC_LIB8TION_TRIG_H
3
7
10
22
23#if defined(USE_SIN_32)
24
25#define sin16 fl::sin16lut
26#define cos16 fl::cos16lut
27
28#include "fl/sin32.h"
29
30#elif defined(__AVR__)
31
33#define sin16 sin16_avr
34
43LIB8STATIC int16_t sin16_avr(uint16_t theta) {
44 static const uint8_t data[] = {
45 0, 0, 49, 0, 6393 % 256, 6393 / 256, 48, 0,
46 12539 % 256, 12539 / 256, 44, 0, 18204 % 256, 18204 / 256, 38, 0,
47 23170 % 256, 23170 / 256, 31, 0, 27245 % 256, 27245 / 256, 23, 0,
48 30273 % 256, 30273 / 256, 14, 0, 32137 % 256, 32137 / 256, 4 /*,0*/};
49
50 uint16_t offset = (theta & 0x3FFF);
51
52 // AVR doesn't have a multi-bit shift instruction,
53 // so if we say "offset >>= 3", gcc makes a tiny loop.
54 // Inserting empty volatile statements between each
55 // bit shift forces gcc to unroll the loop.
56 offset >>= 1; // 0..8191
57 asm volatile("");
58 offset >>= 1; // 0..4095
59 asm volatile("");
60 offset >>= 1; // 0..2047
61
62 if (theta & 0x4000)
63 offset = 2047 - offset;
64
65 uint8_t sectionX4;
66 sectionX4 = offset / 256;
67 sectionX4 *= 4;
68
69 uint8_t m;
70
71 union {
72 uint16_t b;
73 struct {
74 uint8_t blo;
75 uint8_t bhi;
76 };
77 } u;
78
79 // in effect u.b = blo + (256 * bhi);
80 u.blo = data[sectionX4];
81 u.bhi = data[sectionX4 + 1];
82 m = data[sectionX4 + 2];
83
84 uint8_t secoffset8 = (uint8_t)(offset) / 2;
85
86 uint16_t mx = m * secoffset8;
87
88 int16_t y = mx + u.b;
89 if (theta & 0x8000)
90 y = -y;
91
92 return y;
93}
94
95#else
96
98#define sin16 sin16_C
99
108LIB8STATIC int16_t sin16_C(uint16_t theta) {
109 static const uint16_t base[] = {0, 6393, 12539, 18204,
110 23170, 27245, 30273, 32137};
111 static const uint8_t slope[] = {49, 48, 44, 38, 31, 23, 14, 4};
112
113 uint16_t offset = (theta & 0x3FFF) >> 3; // 0..2047
114 if (theta & 0x4000)
115 offset = 2047 - offset;
116
117 uint8_t section = offset / 256; // 0..7
118 uint16_t b = base[section];
119 uint8_t m = slope[section];
120
121 uint8_t secoffset8 = (uint8_t)(offset) / 2;
122
123 uint16_t mx = m * secoffset8;
124 int16_t y = mx + b;
125
126 if (theta & 0x8000)
127 y = -y;
128
129 return y;
130}
131
132#endif
133
142#ifndef USE_SIN_32
143LIB8STATIC int16_t cos16(uint16_t theta) { return sin16(theta + 16384); }
144#endif
145
147// sin8() and cos8()
148// Fast 8-bit approximations of sin(x) & cos(x).
149
151const uint8_t b_m16_interleave[] = {0, 49, 49, 41, 90, 27, 117, 10};
152
153#if defined(__AVR__) && !defined(LIB8_ATTINY)
155#define sin8 sin8_avr
156
165LIB8STATIC uint8_t sin8_avr(uint8_t theta) {
166 uint8_t offset = theta;
167
168 asm volatile("sbrc %[theta],6 \n\t"
169 "com %[offset] \n\t"
170 : [theta] "+r"(theta), [offset] "+r"(offset));
171
172 offset &= 0x3F; // 0..63
173
174 uint8_t secoffset = offset & 0x0F; // 0..15
175 if (theta & 0x40)
176 ++secoffset;
177
178 uint8_t m16;
179 uint8_t b;
180
181 uint8_t section = offset >> 4; // 0..3
182 uint8_t s2 = section * 2;
183
184 const uint8_t *p = b_m16_interleave;
185 p += s2;
186 b = *p;
187 ++p;
188 m16 = *p;
189
190 uint8_t mx;
191 uint8_t xr1;
192 asm volatile("mul %[m16],%[secoffset] \n\t"
193 "mov %[mx],r0 \n\t"
194 "mov %[xr1],r1 \n\t"
195 "eor r1, r1 \n\t"
196 "swap %[mx] \n\t"
197 "andi %[mx],0x0F \n\t"
198 "swap %[xr1] \n\t"
199 "andi %[xr1], 0xF0 \n\t"
200 "or %[mx], %[xr1] \n\t"
201 : [mx] "=d"(mx), [xr1] "=d"(xr1)
202 : [m16] "d"(m16), [secoffset] "d"(secoffset));
203
204 int8_t y = mx + b;
205 if (theta & 0x80)
206 y = -y;
207
208 y += 128;
209
210 return y;
211}
212
213#else
214
216#define sin8 sin8_C
217
226LIB8STATIC uint8_t sin8_C(uint8_t theta) {
227 uint8_t offset = theta;
228 if (theta & 0x40) {
229 offset = (uint8_t)255 - offset;
230 }
231 offset &= 0x3F; // 0..63
232
233 uint8_t secoffset = offset & 0x0F; // 0..15
234 if (theta & 0x40)
235 ++secoffset;
236
237 uint8_t section = offset >> 4; // 0..3
238 uint8_t s2 = section * 2;
239 const uint8_t *p = b_m16_interleave;
240 p += s2;
241 uint8_t b = *p;
242 ++p;
243 uint8_t m16 = *p;
244
245 uint8_t mx = (m16 * secoffset) >> 4;
246
247 int8_t y = mx + b;
248 if (theta & 0x80)
249 y = -y;
250
251 y += 128;
252
253 return y;
254}
255
256#endif
257
266LIB8STATIC uint8_t cos8(uint8_t theta) { return sin8(theta + 64); }
267
270
271#endif
uint32_t y[NUM_LAYERS]
Definition Fire2023.ino:81
LIB8STATIC int16_t cos16(uint16_t theta)
Fast 16-bit approximation of cos(x).
Definition trig8.h:143
LIB8STATIC int16_t sin16_C(uint16_t theta)
Fast 16-bit approximation of sin(x).
Definition trig8.h:108
LIB8STATIC uint8_t cos8(uint8_t theta)
Fast 8-bit approximation of cos(x).
Definition trig8.h:266
LIB8STATIC uint8_t sin8_C(uint8_t theta)
Fast 8-bit approximation of sin(x).
Definition trig8.h:226
#define sin16
Platform-independent alias of the fast sin implementation.
Definition trig8.h:98
const uint8_t b_m16_interleave[]
Pre-calculated lookup table used in sin8() and cos8() functions.
Definition trig8.h:151
#define sin8
Platform-independent alias of the fast sin implementation.
Definition trig8.h:216
#define LIB8STATIC
Define a LIB8TION member function as static inline with an "unused" attribute.
Definition lib8static.h:10
static FASTLED_NAMESPACE_BEGIN uint8_t const p[]
Definition noise.cpp:56