FastLED 3.7.8
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(__AVR__)
24
26#define sin16 sin16_avr
27
36LIB8STATIC int16_t sin16_avr(uint16_t theta) {
37 static const uint8_t data[] = {
38 0, 0, 49, 0, 6393 % 256, 6393 / 256, 48, 0,
39 12539 % 256, 12539 / 256, 44, 0, 18204 % 256, 18204 / 256, 38, 0,
40 23170 % 256, 23170 / 256, 31, 0, 27245 % 256, 27245 / 256, 23, 0,
41 30273 % 256, 30273 / 256, 14, 0, 32137 % 256, 32137 / 256, 4 /*,0*/};
42
43 uint16_t offset = (theta & 0x3FFF);
44
45 // AVR doesn't have a multi-bit shift instruction,
46 // so if we say "offset >>= 3", gcc makes a tiny loop.
47 // Inserting empty volatile statements between each
48 // bit shift forces gcc to unroll the loop.
49 offset >>= 1; // 0..8191
50 asm volatile("");
51 offset >>= 1; // 0..4095
52 asm volatile("");
53 offset >>= 1; // 0..2047
54
55 if (theta & 0x4000)
56 offset = 2047 - offset;
57
58 uint8_t sectionX4;
59 sectionX4 = offset / 256;
60 sectionX4 *= 4;
61
62 uint8_t m;
63
64 union {
65 uint16_t b;
66 struct {
67 uint8_t blo;
68 uint8_t bhi;
69 };
70 } u;
71
72 // in effect u.b = blo + (256 * bhi);
73 u.blo = data[sectionX4];
74 u.bhi = data[sectionX4 + 1];
75 m = data[sectionX4 + 2];
76
77 uint8_t secoffset8 = (uint8_t)(offset) / 2;
78
79 uint16_t mx = m * secoffset8;
80
81 int16_t y = mx + u.b;
82 if (theta & 0x8000)
83 y = -y;
84
85 return y;
86}
87
88#else
89
91#define sin16 sin16_C
92
101LIB8STATIC int16_t sin16_C(uint16_t theta) {
102 static const uint16_t base[] = {0, 6393, 12539, 18204,
103 23170, 27245, 30273, 32137};
104 static const uint8_t slope[] = {49, 48, 44, 38, 31, 23, 14, 4};
105
106 uint16_t offset = (theta & 0x3FFF) >> 3; // 0..2047
107 if (theta & 0x4000)
108 offset = 2047 - offset;
109
110 uint8_t section = offset / 256; // 0..7
111 uint16_t b = base[section];
112 uint8_t m = slope[section];
113
114 uint8_t secoffset8 = (uint8_t)(offset) / 2;
115
116 uint16_t mx = m * secoffset8;
117 int16_t y = mx + b;
118
119 if (theta & 0x8000)
120 y = -y;
121
122 return y;
123}
124
125#endif
126
135LIB8STATIC int16_t cos16(uint16_t theta) { return sin16(theta + 16384); }
136
138// sin8() and cos8()
139// Fast 8-bit approximations of sin(x) & cos(x).
140
142const uint8_t b_m16_interleave[] = {0, 49, 49, 41, 90, 27, 117, 10};
143
144#if defined(__AVR__) && !defined(LIB8_ATTINY)
146#define sin8 sin8_avr
147
156LIB8STATIC uint8_t sin8_avr(uint8_t theta) {
157 uint8_t offset = theta;
158
159 asm volatile("sbrc %[theta],6 \n\t"
160 "com %[offset] \n\t"
161 : [theta] "+r"(theta), [offset] "+r"(offset));
162
163 offset &= 0x3F; // 0..63
164
165 uint8_t secoffset = offset & 0x0F; // 0..15
166 if (theta & 0x40)
167 ++secoffset;
168
169 uint8_t m16;
170 uint8_t b;
171
172 uint8_t section = offset >> 4; // 0..3
173 uint8_t s2 = section * 2;
174
175 const uint8_t *p = b_m16_interleave;
176 p += s2;
177 b = *p;
178 ++p;
179 m16 = *p;
180
181 uint8_t mx;
182 uint8_t xr1;
183 asm volatile("mul %[m16],%[secoffset] \n\t"
184 "mov %[mx],r0 \n\t"
185 "mov %[xr1],r1 \n\t"
186 "eor r1, r1 \n\t"
187 "swap %[mx] \n\t"
188 "andi %[mx],0x0F \n\t"
189 "swap %[xr1] \n\t"
190 "andi %[xr1], 0xF0 \n\t"
191 "or %[mx], %[xr1] \n\t"
192 : [mx] "=d"(mx), [xr1] "=d"(xr1)
193 : [m16] "d"(m16), [secoffset] "d"(secoffset));
194
195 int8_t y = mx + b;
196 if (theta & 0x80)
197 y = -y;
198
199 y += 128;
200
201 return y;
202}
203
204#else
205
207#define sin8 sin8_C
208
217LIB8STATIC uint8_t sin8_C(uint8_t theta) {
218 uint8_t offset = theta;
219 if (theta & 0x40) {
220 offset = (uint8_t)255 - offset;
221 }
222 offset &= 0x3F; // 0..63
223
224 uint8_t secoffset = offset & 0x0F; // 0..15
225 if (theta & 0x40)
226 ++secoffset;
227
228 uint8_t section = offset >> 4; // 0..3
229 uint8_t s2 = section * 2;
230 const uint8_t *p = b_m16_interleave;
231 p += s2;
232 uint8_t b = *p;
233 ++p;
234 uint8_t m16 = *p;
235
236 uint8_t mx = (m16 * secoffset) >> 4;
237
238 int8_t y = mx + b;
239 if (theta & 0x80)
240 y = -y;
241
242 y += 128;
243
244 return y;
245}
246
247#endif
248
257LIB8STATIC uint8_t cos8(uint8_t theta) { return sin8(theta + 64); }
258
261
262#endif
LIB8STATIC int16_t cos16(uint16_t theta)
Fast 16-bit approximation of cos(x).
Definition trig8.h:135
LIB8STATIC int16_t sin16_C(uint16_t theta)
Fast 16-bit approximation of sin(x).
Definition trig8.h:101
LIB8STATIC uint8_t cos8(uint8_t theta)
Fast 8-bit approximation of cos(x).
Definition trig8.h:257
LIB8STATIC uint8_t sin8_C(uint8_t theta)
Fast 8-bit approximation of sin(x).
Definition trig8.h:217
#define sin16
Platform-independent alias of the fast sin implementation.
Definition trig8.h:91
const uint8_t b_m16_interleave[]
Pre-calculated lookup table used in sin8() and cos8() functions.
Definition trig8.h:142
#define sin8
Platform-independent alias of the fast sin implementation.
Definition trig8.h:207
#define LIB8STATIC
Define a LIB8TION member function as static inline with an "unused" attribute.
Definition lib8tion.h:22