FastLED 3.9.15
Loading...
Searching...
No Matches
trig8.h
Go to the documentation of this file.
1#pragma once
2
3#ifndef __INC_LIB8TION_TRIG_H
4#define __INC_LIB8TION_TRIG_H
5
6#include "fl/stdint.h"
8
10
17
21
24
36
37#if defined(USE_SIN_32)
38
39#define sin16 fl::sin16lut
40#define cos16 fl::cos16lut
41
42#include "fl/sin32.h"
43
44#elif defined(__AVR__)
45
47#define sin16 sin16_avr
48
57LIB8STATIC int16_t sin16_avr(uint16_t theta) {
58 static const uint8_t data[] = {
59 0, 0, 49, 0, 6393 % 256, 6393 / 256, 48, 0,
60 12539 % 256, 12539 / 256, 44, 0, 18204 % 256, 18204 / 256, 38, 0,
61 23170 % 256, 23170 / 256, 31, 0, 27245 % 256, 27245 / 256, 23, 0,
62 30273 % 256, 30273 / 256, 14, 0, 32137 % 256, 32137 / 256, 4 /*,0*/};
63
64 uint16_t offset = (theta & 0x3FFF);
65
66 // AVR doesn't have a multi-bit shift instruction,
67 // so if we say "offset >>= 3", gcc makes a tiny loop.
68 // Inserting empty volatile statements between each
69 // bit shift forces gcc to unroll the loop.
70 offset >>= 1; // 0..8191
71 asm volatile("");
72 offset >>= 1; // 0..4095
73 asm volatile("");
74 offset >>= 1; // 0..2047
75
76 if (theta & 0x4000)
77 offset = 2047 - offset;
78
79 uint8_t sectionX4;
80 sectionX4 = offset / 256;
81 sectionX4 *= 4;
82
83 uint8_t m;
84
85 union {
86 uint16_t b;
87 struct {
88 uint8_t blo;
89 uint8_t bhi;
90 };
91 } u;
92
93 // in effect u.b = blo + (256 * bhi);
94 u.blo = data[sectionX4];
95 u.bhi = data[sectionX4 + 1];
96 m = data[sectionX4 + 2];
97
98 uint8_t secoffset8 = (uint8_t)(offset) / 2;
99
100 uint16_t mx = m * secoffset8;
101
102 int16_t y = mx + u.b;
103 if (theta & 0x8000)
104 y = -y;
105
106 return y;
107}
108
109#else
110
112#define sin16 sin16_C
113
122LIB8STATIC int16_t sin16_C(uint16_t theta) {
123 static const uint16_t base[] = {0, 6393, 12539, 18204,
124 23170, 27245, 30273, 32137};
125 static const uint8_t slope[] = {49, 48, 44, 38, 31, 23, 14, 4};
126
127 uint16_t offset = (theta & 0x3FFF) >> 3; // 0..2047
128 if (theta & 0x4000)
129 offset = 2047 - offset;
130
131 uint8_t section = offset / 256; // 0..7
132 uint16_t b = base[section];
133 uint8_t m = slope[section];
134
135 uint8_t secoffset8 = (uint8_t)(offset) / 2;
136
137 uint16_t mx = m * secoffset8;
138 int16_t y = mx + b;
139
140 if (theta & 0x8000)
141 y = -y;
142
143 return y;
144}
145
146#endif
147
156#ifndef USE_SIN_32
157LIB8STATIC int16_t cos16(uint16_t theta) { return sin16(theta + 16384); }
158#endif
159
161// sin8() and cos8()
162// Fast 8-bit approximations of sin(x) & cos(x).
163
165const uint8_t b_m16_interleave[] = {0, 49, 49, 41, 90, 27, 117, 10};
166
167#if defined(__AVR__) && !defined(LIB8_ATTINY)
169#define sin8 sin8_avr
170
179LIB8STATIC uint8_t sin8_avr(uint8_t theta) {
180 uint8_t offset = theta;
181
182 asm volatile("sbrc %[theta],6 \n\t"
183 "com %[offset] \n\t"
184 : [theta] "+r"(theta), [offset] "+r"(offset));
185
186 offset &= 0x3F; // 0..63
187
188 uint8_t secoffset = offset & 0x0F; // 0..15
189 if (theta & 0x40)
190 ++secoffset;
191
192 uint8_t m16;
193 uint8_t b;
194
195 uint8_t section = offset >> 4; // 0..3
196 uint8_t s2 = section * 2;
197
198 const uint8_t *p = b_m16_interleave;
199 p += s2;
200 b = *p;
201 ++p;
202 m16 = *p;
203
204 uint8_t mx;
205 uint8_t xr1;
206 asm volatile("mul %[m16],%[secoffset] \n\t"
207 "mov %[mx],r0 \n\t"
208 "mov %[xr1],r1 \n\t"
209 "eor r1, r1 \n\t"
210 "swap %[mx] \n\t"
211 "andi %[mx],0x0F \n\t"
212 "swap %[xr1] \n\t"
213 "andi %[xr1], 0xF0 \n\t"
214 "or %[mx], %[xr1] \n\t"
215 : [mx] "=d"(mx), [xr1] "=d"(xr1)
216 : [m16] "d"(m16), [secoffset] "d"(secoffset));
217
218 int8_t y = mx + b;
219 if (theta & 0x80)
220 y = -y;
221
222 y += 128;
223
224 return y;
225}
226
227#else
228
230#define sin8 sin8_C
231
240LIB8STATIC uint8_t sin8_C(uint8_t theta) {
241 uint8_t offset = theta;
242 if (theta & 0x40) {
243 offset = (uint8_t)255 - offset;
244 }
245 offset &= 0x3F; // 0..63
246
247 uint8_t secoffset = offset & 0x0F; // 0..15
248 if (theta & 0x40)
249 ++secoffset;
250
251 uint8_t section = offset >> 4; // 0..3
252 uint8_t s2 = section * 2;
253 const uint8_t *p = b_m16_interleave;
254 p += s2;
255 uint8_t b = *p;
256 ++p;
257 uint8_t m16 = *p;
258
259 uint8_t mx = (m16 * secoffset) >> 4;
260
261 int8_t y = mx + b;
262 if (theta & 0x80)
263 y = -y;
264
265 y += 128;
266
267 return y;
268}
269
270#endif
271
280LIB8STATIC uint8_t cos8(uint8_t theta) { return sin8(theta + 64); }
281
284
285#endif
286
int y
Definition simple.h:93
#define FL_DISABLE_WARNING_RETURN_TYPE
#define FL_DISABLE_WARNING_IMPLICIT_INT_CONVERSION
#define FL_DISABLE_WARNING_PUSH
#define FL_DISABLE_WARNING_SIGN_CONVERSION
#define FL_DISABLE_WARNING_POP
#define FL_DISABLE_WARNING_UNUSED_PARAMETER
#define FL_DISABLE_WARNING_FLOAT_CONVERSION
UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f)
LIB8STATIC int16_t cos16(uint16_t theta)
Fast 16-bit approximation of cos(x).
Definition trig8.h:157
LIB8STATIC int16_t sin16_C(uint16_t theta)
Fast 16-bit approximation of sin(x).
Definition trig8.h:122
LIB8STATIC uint8_t cos8(uint8_t theta)
Fast 8-bit approximation of cos(x).
Definition trig8.h:280
LIB8STATIC uint8_t sin8_C(uint8_t theta)
Fast 8-bit approximation of sin(x).
Definition trig8.h:240
#define sin16
Platform-independent alias of the fast sin implementation.
Definition trig8.h:112
const uint8_t b_m16_interleave[]
Pre-calculated lookup table used in sin8() and cos8() functions.
Definition trig8.h:165
#define sin8
Platform-independent alias of the fast sin implementation.
Definition trig8.h:230
#define LIB8STATIC
Define a LIB8TION member function as static inline with an "unused" attribute.
Definition lib8static.h:10
Defines static inlining macros for lib8tion functions.