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 <stdint.h>
8
12
15
27
28#if defined(USE_SIN_32)
29
30#define sin16 fl::sin16lut
31#define cos16 fl::cos16lut
32
33#include "fl/sin32.h"
34
35#elif defined(__AVR__)
36
38#define sin16 sin16_avr
39
48LIB8STATIC int16_t sin16_avr(uint16_t theta) {
49 static const uint8_t data[] = {
50 0, 0, 49, 0, 6393 % 256, 6393 / 256, 48, 0,
51 12539 % 256, 12539 / 256, 44, 0, 18204 % 256, 18204 / 256, 38, 0,
52 23170 % 256, 23170 / 256, 31, 0, 27245 % 256, 27245 / 256, 23, 0,
53 30273 % 256, 30273 / 256, 14, 0, 32137 % 256, 32137 / 256, 4 /*,0*/};
54
55 uint16_t offset = (theta & 0x3FFF);
56
57 // AVR doesn't have a multi-bit shift instruction,
58 // so if we say "offset >>= 3", gcc makes a tiny loop.
59 // Inserting empty volatile statements between each
60 // bit shift forces gcc to unroll the loop.
61 offset >>= 1; // 0..8191
62 asm volatile("");
63 offset >>= 1; // 0..4095
64 asm volatile("");
65 offset >>= 1; // 0..2047
66
67 if (theta & 0x4000)
68 offset = 2047 - offset;
69
70 uint8_t sectionX4;
71 sectionX4 = offset / 256;
72 sectionX4 *= 4;
73
74 uint8_t m;
75
76 union {
77 uint16_t b;
78 struct {
79 uint8_t blo;
80 uint8_t bhi;
81 };
82 } u;
83
84 // in effect u.b = blo + (256 * bhi);
85 u.blo = data[sectionX4];
86 u.bhi = data[sectionX4 + 1];
87 m = data[sectionX4 + 2];
88
89 uint8_t secoffset8 = (uint8_t)(offset) / 2;
90
91 uint16_t mx = m * secoffset8;
92
93 int16_t y = mx + u.b;
94 if (theta & 0x8000)
95 y = -y;
96
97 return y;
98}
99
100#else
101
103#define sin16 sin16_C
104
113LIB8STATIC int16_t sin16_C(uint16_t theta) {
114 static const uint16_t base[] = {0, 6393, 12539, 18204,
115 23170, 27245, 30273, 32137};
116 static const uint8_t slope[] = {49, 48, 44, 38, 31, 23, 14, 4};
117
118 uint16_t offset = (theta & 0x3FFF) >> 3; // 0..2047
119 if (theta & 0x4000)
120 offset = 2047 - offset;
121
122 uint8_t section = offset / 256; // 0..7
123 uint16_t b = base[section];
124 uint8_t m = slope[section];
125
126 uint8_t secoffset8 = (uint8_t)(offset) / 2;
127
128 uint16_t mx = m * secoffset8;
129 int16_t y = mx + b;
130
131 if (theta & 0x8000)
132 y = -y;
133
134 return y;
135}
136
137#endif
138
147#ifndef USE_SIN_32
148LIB8STATIC int16_t cos16(uint16_t theta) { return sin16(theta + 16384); }
149#endif
150
152// sin8() and cos8()
153// Fast 8-bit approximations of sin(x) & cos(x).
154
156const uint8_t b_m16_interleave[] = {0, 49, 49, 41, 90, 27, 117, 10};
157
158#if defined(__AVR__) && !defined(LIB8_ATTINY)
160#define sin8 sin8_avr
161
170LIB8STATIC uint8_t sin8_avr(uint8_t theta) {
171 uint8_t offset = theta;
172
173 asm volatile("sbrc %[theta],6 \n\t"
174 "com %[offset] \n\t"
175 : [theta] "+r"(theta), [offset] "+r"(offset));
176
177 offset &= 0x3F; // 0..63
178
179 uint8_t secoffset = offset & 0x0F; // 0..15
180 if (theta & 0x40)
181 ++secoffset;
182
183 uint8_t m16;
184 uint8_t b;
185
186 uint8_t section = offset >> 4; // 0..3
187 uint8_t s2 = section * 2;
188
189 const uint8_t *p = b_m16_interleave;
190 p += s2;
191 b = *p;
192 ++p;
193 m16 = *p;
194
195 uint8_t mx;
196 uint8_t xr1;
197 asm volatile("mul %[m16],%[secoffset] \n\t"
198 "mov %[mx],r0 \n\t"
199 "mov %[xr1],r1 \n\t"
200 "eor r1, r1 \n\t"
201 "swap %[mx] \n\t"
202 "andi %[mx],0x0F \n\t"
203 "swap %[xr1] \n\t"
204 "andi %[xr1], 0xF0 \n\t"
205 "or %[mx], %[xr1] \n\t"
206 : [mx] "=d"(mx), [xr1] "=d"(xr1)
207 : [m16] "d"(m16), [secoffset] "d"(secoffset));
208
209 int8_t y = mx + b;
210 if (theta & 0x80)
211 y = -y;
212
213 y += 128;
214
215 return y;
216}
217
218#else
219
221#define sin8 sin8_C
222
231LIB8STATIC uint8_t sin8_C(uint8_t theta) {
232 uint8_t offset = theta;
233 if (theta & 0x40) {
234 offset = (uint8_t)255 - offset;
235 }
236 offset &= 0x3F; // 0..63
237
238 uint8_t secoffset = offset & 0x0F; // 0..15
239 if (theta & 0x40)
240 ++secoffset;
241
242 uint8_t section = offset >> 4; // 0..3
243 uint8_t s2 = section * 2;
244 const uint8_t *p = b_m16_interleave;
245 p += s2;
246 uint8_t b = *p;
247 ++p;
248 uint8_t m16 = *p;
249
250 uint8_t mx = (m16 * secoffset) >> 4;
251
252 int8_t y = mx + b;
253 if (theta & 0x80)
254 y = -y;
255
256 y += 128;
257
258 return y;
259}
260
261#endif
262
271LIB8STATIC uint8_t cos8(uint8_t theta) { return sin8(theta + 64); }
272
275
276#endif
int y
Definition Audio.ino:72
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:148
LIB8STATIC int16_t sin16_C(uint16_t theta)
Fast 16-bit approximation of sin(x).
Definition trig8.h:113
LIB8STATIC uint8_t cos8(uint8_t theta)
Fast 8-bit approximation of cos(x).
Definition trig8.h:271
LIB8STATIC uint8_t sin8_C(uint8_t theta)
Fast 8-bit approximation of sin(x).
Definition trig8.h:231
#define sin16
Platform-independent alias of the fast sin implementation.
Definition trig8.h:103
const uint8_t b_m16_interleave[]
Pre-calculated lookup table used in sin8() and cos8() functions.
Definition trig8.h:156
#define sin8
Platform-independent alias of the fast sin implementation.
Definition trig8.h:221
#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.
static FASTLED_NAMESPACE_BEGIN uint8_t const p[]
Definition noise.cpp:30