├── AudioLogic.h
├── AudioPatterns.h
├── Commands.h
├── Drawing.h
├── Effects.h
├── Fire2012Rainbow.h
├── Fire2012WithPalette.h
├── FireBlue.h
├── FireChemical.h
├── FireElectricBlue.h
├── FireGreen.h
├── FireOrange.h
├── FirePurple.h
├── FireRainbow.h
├── FireRed.h
├── FireWhite.h
├── GradientPalettes.h
├── LEDEffectLampProject.ino
├── LICENSE
├── Noise.h
├── Pulse.h
├── README.md
├── VariableList.txt
└── Wave.h
/AudioLogic.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Torch: https://github.com/evilgeniuslabs/torch
3 | * Copyright (C) 2015 Jason Coon
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | #define MSGEQ7_STROBE_PIN 2
20 | #define MSGEQ7_RESET_PIN 3
21 | #define MSGEQ7_LEFT_PIN A0
22 | #define MSGEQ7_RIGHT_PIN A1
23 |
24 | const uint8_t bandCount = 7;
25 |
26 | int levelsLeft[bandCount];
27 | int peaksLeft[bandCount];
28 |
29 | int levelsRight[bandCount];
30 | int peaksRight[bandCount];
31 |
32 | static const uint8_t peakDecay = (1024 / MATRIX_HEIGHT) / 6;
33 | bool drawPeaks = true;
34 |
35 | int noiseCorrection[bandCount] = {
36 | -55, -50, -45, -55, -40, -55, -50,
37 | //0, 0, 0, 0, 0, 0, 0
38 | };
39 |
40 | uint8_t bandOffset = 3;
41 | uint8_t horizontalPixelsPerBand = MATRIX_WIDTH / (bandCount * 2);
42 | uint8_t levelsPerVerticalPixel = 63; // 1024 / MATRIX_HEIGHT;
43 | uint8_t levelsPerHue = 1024 / 256;
44 |
45 | void initializeAudio() {
46 | pinMode(MSGEQ7_LEFT_PIN, INPUT);
47 | pinMode(MSGEQ7_RIGHT_PIN, INPUT);
48 | pinMode(MSGEQ7_RESET_PIN, OUTPUT);
49 | pinMode(MSGEQ7_STROBE_PIN, OUTPUT);
50 | digitalWrite(MSGEQ7_RESET_PIN, LOW);
51 | digitalWrite(MSGEQ7_STROBE_PIN, HIGH);
52 | }
53 |
54 | void readAudio() {
55 | digitalWrite(MSGEQ7_RESET_PIN, HIGH);
56 | digitalWrite(MSGEQ7_RESET_PIN, LOW);
57 |
58 | int levelLeft;
59 | int levelRight;
60 |
61 | for (uint8_t band = 0; band < bandCount; band++) {
62 | digitalWrite(MSGEQ7_STROBE_PIN, LOW);
63 | delayMicroseconds(30);
64 |
65 | levelLeft = analogRead(MSGEQ7_LEFT_PIN);
66 | levelRight = analogRead(MSGEQ7_RIGHT_PIN);
67 | digitalWrite(MSGEQ7_STROBE_PIN, HIGH);
68 |
69 | levelLeft += noiseCorrection[band];
70 | levelRight += noiseCorrection[band];
71 |
72 | // if (levelLeft < 0) levelLeft = 0;
73 | // if (levelLeft > 1023) levelLeft = 1023;
74 | //
75 | // if (levelRight < 0) levelRight = 0;
76 | // if (levelRight > 1023) levelRight = 1023;
77 |
78 | levelsLeft[band] = levelLeft;
79 | levelsRight[band] = levelRight;
80 |
81 | // if (levelLeft >= peaksLeft[band]) {
82 | peaksLeft[band] = levelLeft;
83 | // }
84 | // else if (peaksLeft[band] > 0) {
85 | // peaksLeft[band] = peaksLeft[band] - peakDecay;
86 | // if(peaksLeft[band] < 0) peaksLeft[band] = 0;
87 | // }
88 | //
89 | // if (levelRight >= peaksRight[band]) {
90 | peaksRight[band] = levelRight;
91 | // }
92 | // else if (peaksRight[band] > 0) {
93 | // peaksRight[band] = peaksRight[band] - peakDecay;
94 | // if(peaksRight[band] < 0) peaksRight[band] = 0;
95 | // }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/AudioPatterns.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Torch: https://github.com/evilgeniuslabs/torch
3 | * Copyright (C) 2015 Jason Coon
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | uint16_t AudioAnalyzerColumns() {
20 | fill_solid(leds, NUM_LEDS, CRGB::Black);
21 |
22 | for (uint8_t bandIndex = 0; bandIndex < bandCount; bandIndex++) {
23 | int levelLeft = levelsLeft[bandIndex];
24 | int levelRight = levelsRight[bandIndex];
25 |
26 | if (drawPeaks) {
27 | levelLeft = peaksLeft[bandIndex];
28 | levelRight = peaksRight[bandIndex];
29 | }
30 |
31 | CRGB colorLeft = ColorFromPalette(palette, levelLeft / levelsPerHue);
32 | CRGB colorRight = ColorFromPalette(palette, levelRight / levelsPerHue);
33 |
34 | uint8_t x = bandIndex + bandOffset;
35 | if (x >= MATRIX_WIDTH)
36 | x -= MATRIX_WIDTH;
37 |
38 | drawFastVLine(x, (MATRIX_HEIGHT - 1) - levelLeft / levelsPerVerticalPixel, MATRIX_HEIGHT - 1, colorLeft);
39 | drawFastVLine(x + bandCount, (MATRIX_HEIGHT - 1) - levelRight / levelsPerVerticalPixel, MATRIX_HEIGHT - 1, colorRight);
40 | }
41 |
42 | return 1;
43 | }
44 |
45 | //===========================================
46 | uint16_t AudioAnalyzerColumnsSolid() {
47 | fill_solid(leds, NUM_LEDS, CRGB::Black);
48 |
49 | for (uint8_t bandIndex = 0; bandIndex < bandCount; bandIndex++) {
50 | int levelLeft = levelsLeft[bandIndex];
51 | int levelRight = levelsRight[bandIndex];
52 |
53 | if (drawPeaks) {
54 | levelLeft = peaksLeft[bandIndex];
55 | levelRight = peaksRight[bandIndex];
56 | }
57 |
58 | CRGB colorLeft = ColorFromPalette(palette, gHue);
59 | CRGB colorRight = ColorFromPalette(palette, gHue);
60 |
61 | uint8_t x = bandIndex + bandOffset;
62 | if (x >= MATRIX_WIDTH)
63 | x -= MATRIX_WIDTH;
64 |
65 | drawFastVLine(x, (MATRIX_HEIGHT - 1) - levelLeft / levelsPerVerticalPixel, MATRIX_HEIGHT - 1, colorLeft);
66 | drawFastVLine(x + bandCount, (MATRIX_HEIGHT - 1) - levelRight / levelsPerVerticalPixel, MATRIX_HEIGHT - 1, colorRight);
67 | }
68 |
69 | return 1;
70 | }
71 |
72 | //===========================================
73 | uint16_t AudioAnalyzerPixels() {
74 | fill_solid(leds, NUM_LEDS, CRGB::Black);
75 |
76 | for (uint8_t bandIndex = 0; bandIndex < bandCount; bandIndex++) {
77 | int levelLeft = levelsLeft[bandIndex];
78 | int levelRight = levelsRight[bandIndex];
79 |
80 | if (drawPeaks) {
81 | levelLeft = peaksLeft[bandIndex];
82 | levelRight = peaksRight[bandIndex];
83 | }
84 |
85 | CRGB colorLeft = ColorFromPalette(palette, levelLeft / levelsPerHue);
86 | CRGB colorRight = ColorFromPalette(palette, levelRight / levelsPerHue);
87 |
88 | uint8_t x = bandIndex + bandOffset;
89 | if (x >= MATRIX_WIDTH)
90 | x -= MATRIX_WIDTH;
91 |
92 | leds[XY(x, (MATRIX_HEIGHT - 1) - levelLeft / levelsPerVerticalPixel)] = colorLeft;
93 | leds[XY(x + bandCount, (MATRIX_HEIGHT - 1) - levelLeft / levelsPerVerticalPixel)] = colorRight;
94 | }
95 |
96 | return 0;
97 | }
98 |
99 | //===========================================
100 | uint16_t AudioFallingSpectrogram() {
101 | moveDown();
102 |
103 | for (uint8_t bandIndex = 0; bandIndex < bandCount; bandIndex++) {
104 | int levelLeft = levelsLeft[bandIndex];
105 | int levelRight = levelsRight[bandIndex];
106 |
107 | if (drawPeaks) {
108 | levelLeft = peaksLeft[bandIndex];
109 | levelRight = peaksRight[bandIndex];
110 | }
111 |
112 | if (levelLeft <= 8) levelLeft = 0;
113 | if (levelRight <= 8) levelRight = 0;
114 |
115 | CRGB colorLeft;
116 | CRGB colorRight;
117 |
118 | if (currentPaletteIndex < 2) { // invert the first two palettes
119 | colorLeft = ColorFromPalette(palette, 205 - (levelLeft / levelsPerHue - 205));
120 | colorRight = ColorFromPalette(palette, 205 - (levelLeft / levelsPerHue - 205));
121 | }
122 | else {
123 | colorLeft = ColorFromPalette(palette, levelLeft / levelsPerHue);
124 | colorRight = ColorFromPalette(palette, levelRight / levelsPerHue);
125 | }
126 |
127 | uint8_t x = bandIndex + bandOffset;
128 | if (x >= MATRIX_WIDTH)
129 | x -= MATRIX_WIDTH;
130 |
131 | leds[XY(x, 0)] = colorLeft;
132 | leds[XY(x + bandCount, 0)] = colorRight;
133 | }
134 |
135 | return 0;
136 | }
137 |
138 | //===========================================
139 | uint16_t AudioFire1() {
140 | moveUp();
141 |
142 | for (uint8_t bandIndex = 0; bandIndex < bandCount; bandIndex++) {
143 | int levelLeft = levelsLeft[bandIndex];
144 | int levelRight = levelsRight[bandIndex];
145 |
146 | if (drawPeaks) {
147 | levelLeft = peaksLeft[bandIndex];
148 | levelRight = peaksRight[bandIndex];
149 | }
150 |
151 | if (levelLeft <= 8) levelLeft = 0;
152 | if (levelRight <= 8) levelRight = 0;
153 |
154 | CRGB colorLeft = ColorFromPalette(HeatColors_p, levelLeft / 5);
155 | CRGB colorRight = ColorFromPalette(HeatColors_p, levelRight / 2);
156 |
157 | uint8_t x = bandIndex + bandOffset;
158 | if (x >= MATRIX_WIDTH)
159 | x -= MATRIX_WIDTH;
160 |
161 | leds[XY(x, MATRIX_HEIGHT - 1)] = colorLeft;
162 | leds[XY(x + bandCount, MATRIX_HEIGHT - 1)] = colorRight;
163 | }
164 |
165 | return 0;
166 | }
167 |
168 | //===========================================
169 | uint16_t AudioFire2() {
170 | moveUp();
171 |
172 | for (uint8_t bandIndex = 0; bandIndex < bandCount; bandIndex++) {
173 | int levelLeft = levelsLeft[bandIndex];
174 | int levelRight = levelsRight[bandIndex];
175 |
176 | if (drawPeaks) {
177 | levelLeft = peaksLeft[bandIndex];
178 | levelRight = peaksRight[bandIndex];
179 | }
180 |
181 | if (levelLeft <= 8) levelLeft = 0;
182 | if (levelRight <= 8) levelRight = 0;
183 |
184 | CRGB colorLeft = ColorFromPalette(OceanColors_p, levelLeft / 5);
185 | CRGB colorRight = ColorFromPalette(OceanColors_p, levelRight / 5);
186 |
187 | uint8_t x = bandIndex + bandOffset;
188 | if (x >= MATRIX_WIDTH)
189 | x -= MATRIX_WIDTH;
190 |
191 | leds[XY(x, MATRIX_HEIGHT - 1)] = colorLeft;
192 | leds[XY(x + bandCount, MATRIX_HEIGHT - 1)] = colorRight;
193 | }
194 |
195 | return 0;
196 | }
197 |
198 | //===========================================
199 | uint16_t AudioFire3() {
200 | static int lastPeak0 = 0;
201 | static int lastPeak6 = 0;
202 | noisespeedx = 0;
203 | noisespeedz = 0;
204 | if (peaksLeft[0] >= lastPeak0) {
205 | noisespeedx = peaksLeft[0] / 32;
206 | }
207 | if (peaksLeft[6] >= lastPeak6) {
208 | noisespeedz = peaksLeft[6] / 128;
209 | }
210 | lastPeak0 = peaksLeft[0];
211 | lastPeak6 = peaksLeft[6];
212 | noisespeedy = 0;
213 | noisescale = 50;
214 | colorLoop = 0;
215 | return drawNoise(HeatColors_p, 60);
216 | }
217 |
218 | //===========================================
219 | uint16_t AudioLavaRainbow() {
220 | static int lastPeak0 = 0;
221 | noisespeedx = 0;
222 | if (peaksLeft[0] >= lastPeak0) {
223 | noisespeedx = peaksLeft[0] / 57;
224 | }
225 | lastPeak0 = peaksLeft[0];
226 | noisespeedy = 3;
227 | noisespeedz = 0;
228 | noisescale = 30;
229 | colorLoop = 0;
230 | return drawNoise(RainbowColors_p);
231 | //return drawNoise(LavaColors_p);
232 | }
233 |
234 | //===========================================
235 | uint16_t AudioLava() {
236 | static int lastPeak0 = 0;
237 | noisespeedx = 0;
238 | if (peaksLeft[0] >= lastPeak0) {
239 | noisespeedx = peaksLeft[0] / 57;
240 | }
241 | lastPeak0 = peaksLeft[0];
242 | noisespeedy = 3;
243 | noisespeedz = 0;
244 | noisescale = 30;
245 | colorLoop = 0;
246 | return drawNoise(LavaColors_p);
247 | }
248 |
249 | //===========================================
250 | uint16_t AudioForest() {
251 | static int lastPeak0 = 0;
252 | noisespeedx = 0;
253 | if (peaksLeft[0] >= lastPeak0) {
254 | noisespeedx = peaksLeft[0] / 57;
255 | }
256 | lastPeak0 = peaksLeft[0];
257 | noisespeedy = 0;
258 | noisespeedz = 0;
259 | noisescale = 120;
260 | colorLoop = 0;
261 | return drawNoise(ForestColors_p);
262 | }
263 |
264 | //===========================================
265 | uint16_t AudioRainbowStripe() {
266 | static int lastPeak0 = 0;
267 | noisespeedy = 0;
268 | if (peaksLeft[0] >= lastPeak0) {
269 | noisespeedy = peaksLeft[0] / 57;
270 | }
271 | lastPeak0 = peaksLeft[0];
272 | noisespeedx = 0;
273 | noisespeedz = 0;
274 | noisescale = 20;
275 | colorLoop = 0;
276 | return drawNoise(RainbowStripeColors_p);
277 | }
278 |
279 | //===========================================
280 | uint16_t AudioParty() {
281 | static int lastPeak0 = 0;
282 | noisespeedx = 0;
283 | if (peaksLeft[0] >= lastPeak0) {
284 | noisespeedx = peaksLeft[0] / 57;
285 | }
286 | lastPeak0 = peaksLeft[0];
287 | noisespeedy = 0;
288 | noisespeedz = 0;
289 | noisescale = 30;
290 | colorLoop = 0;
291 | return drawNoise(PartyColors_p);
292 | }
293 |
294 | //===========================================
295 | uint16_t AudioLavaMagenta() {
296 | static int lastPeak0 = 0;
297 | noisespeedx = 0;
298 | if (peaksLeft[0] >= lastPeak0) {
299 | noisespeedx = peaksLeft[0] / 57;
300 | }
301 | lastPeak0 = peaksLeft[0];
302 | noisespeedy = 0;
303 | noisespeedz = 0;
304 | noisescale = 5;
305 | colorLoop = 0;
306 | //return drawNoise(Magenta_Evening_gp);
307 | return drawNoise(BlacK_Magenta_Red_gp);
308 | //return drawNoise(fire_gp);
309 | }
310 |
311 | //===========================================
312 | uint16_t AudioCloud() {
313 | static int lastPeak0 = 0;
314 | noisespeedx = 0;
315 | if (peaksLeft[0] >= lastPeak0) {
316 | noisespeedx = peaksLeft[0] / 57;
317 | }
318 | lastPeak0 = peaksLeft[0];
319 | noisespeedy = 0;
320 | noisespeedz = 0;
321 | noisescale = 30;
322 | colorLoop = 0;
323 | return drawNoise(CloudColors_p);
324 | }
325 |
326 | //===========================================
327 | uint16_t AudioLava2() {
328 | static int lastPeak0 = 0;
329 | static int lastPeak6 = 0;
330 | noisespeedy = 0;
331 | noisespeedz = 0;
332 | if (peaksLeft[0] >= lastPeak0) {
333 | noisespeedy = peaksLeft[0] / 32;
334 | }
335 | if (peaksLeft[6] >= lastPeak6) {
336 | noisespeedz = peaksLeft[6] / 128;
337 | }
338 | lastPeak0 = peaksLeft[0];
339 | lastPeak6 = peaksLeft[6];
340 | noisespeedx = 0;
341 | noisescale = 50;
342 | colorLoop = 0;
343 | return drawNoise(LavaColors_p);
344 | }
345 |
346 | //===========================================
347 | uint16_t AudioOcean() {
348 | static int lastPeak0 = 0;
349 | noisespeedy = 0;
350 | if (peaksLeft[0] >= lastPeak0) {
351 | noisespeedy = peaksLeft[0] / 57;
352 | }
353 | lastPeak0 = peaksLeft[0];
354 | noisespeedx = 0;
355 | noisespeedz = 0;
356 | noisescale = 90;
357 | colorLoop = 0;
358 | return drawNoise(OceanColors_p);
359 | }
360 |
361 | //===========================================
362 | uint16_t AudioBlackAndWhite() {
363 | SetupBlackAndWhiteStripedPalette();
364 | static int lastPeak0 = 0;
365 | noisespeedy = 0;
366 | if (peaksLeft[0] >= lastPeak0) {
367 | noisespeedy = peaksLeft[0] / 128;
368 | }
369 | lastPeak0 = peaksLeft[0];
370 | noisespeedx = 0;
371 | noisespeedz = 0;
372 | noisescale = 15;
373 | colorLoop = 0;
374 | return drawNoise(blackAndWhiteStripedPalette);
375 | }
376 |
377 | //===========================================
378 | uint16_t AudioBlackAndBlue() {
379 | SetupBlackAndBlueStripedPalette();
380 | static int lastPeak0 = 0;
381 | noisespeedx = 0;
382 | if (peaksLeft[0] >= lastPeak0) {
383 | noisespeedx = peaksLeft[0] / 57;
384 | }
385 | lastPeak0 = peaksLeft[0];
386 | noisespeedy = 0;
387 | noisespeedz = 0;
388 | noisescale = 45;
389 | colorLoop = 0;
390 | return drawNoise(blackAndBlueStripedPalette);
391 | }
392 |
--------------------------------------------------------------------------------
/Commands.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Torch: https://github.com/evilgeniuslabs/torch
3 | * Copyright (C) 2015 Jason Coon
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | #ifndef IrCodes_H
20 | #define IrCodes_H
21 |
22 | enum class InputCommand {
23 | None,
24 | Up,
25 | Down,
26 | Left,
27 | Right,
28 | Select,
29 | Brightness,
30 | PlayMode,
31 | Power,
32 | BrightnessUp,
33 | BrightnessDown,
34 | CyclePalette,
35 | NextPalette,
36 | PreviousPalette,
37 |
38 | Pattern1,
39 | Pattern2,
40 | Pattern3,
41 | Pattern4,
42 | Pattern5,
43 | Pattern6,
44 | Pattern7,
45 | Pattern8,
46 | Pattern9,
47 | Pattern10,
48 | Pattern11,
49 | Pattern12,
50 |
51 | RedUp,
52 | RedDown,
53 | GreenUp,
54 | GreenDown,
55 | BlueUp,
56 | BlueDown,
57 |
58 | Red,
59 | RedOrange,
60 | Orange,
61 | YellowOrange,
62 | Yellow,
63 |
64 | Green,
65 | Lime,
66 | Aqua,
67 | Teal,
68 | Navy,
69 |
70 | Blue,
71 | RoyalBlue,
72 | Purple,
73 | Indigo,
74 | Magenta,
75 |
76 | White,
77 | Pink,
78 | LightPink,
79 | BabyBlue,
80 | LightBlue,
81 | };
82 |
83 | // IR Raw Key Codes for SparkFun remote
84 | #define IRCODE_SPARKFUN_POWER 0x10EFD827 // 284153895
85 | #define IRCODE_SPARKFUN_A 0x10EFF807 //
86 | #define IRCODE_SPARKFUN_B 0x10EF7887
87 | #define IRCODE_SPARKFUN_C 0x10EF58A7
88 | #define IRCODE_SPARKFUN_UP 0x10EFA05F // 284139615
89 | #define IRCODE_SPARKFUN_LEFT 0x10EF10EF
90 | #define IRCODE_SPARKFUN_SELECT 0x10EF20DF
91 | #define IRCODE_SPARKFUN_RIGHT 0x10EF807F
92 | #define IRCODE_SPARKFUN_DOWN 0x10EF00FF
93 | #define IRCODE_SPARKFUN_HELD 0xFFFFFFFF
94 |
95 | // IR Raw Key Codes for Adafruit remote
96 | #define IRCODE_ADAFRUIT_HELD 0x7FFFFFFF // 4294967295
97 | #define IRCODE_ADAFRUIT_VOLUME_UP 0x00FD40BF // 16597183
98 | #define IRCODE_ADAFRUIT_PLAY_PAUSE 0x00FD807F // 16613503
99 | #define IRCODE_ADAFRUIT_VOLUME_DOWN 0x00FD00FF // 16580863
100 | #define IRCODE_ADAFRUIT_SETUP 0x00FD20DF // 16589023
101 | #define IRCODE_ADAFRUIT_UP 0x00FDA05F // 16621663
102 | #define IRCODE_ADAFRUIT_STOP_MODE 0x00FD609F // 16605343
103 | #define IRCODE_ADAFRUIT_LEFT 0x00FD10EF // 16584943
104 | #define IRCODE_ADAFRUIT_ENTER_SAVE 0x00FD906F // 16617583
105 | #define IRCODE_ADAFRUIT_RIGHT 0x00FD50AF // 16601263
106 | #define IRCODE_ADAFRUIT_0_10_PLUS 0x00FD30CF // 16593103
107 | #define IRCODE_ADAFRUIT_DOWN 0x00FDB04F // 16625743
108 | #define IRCODE_ADAFRUIT_BACK 0x00FD708F // 16609423
109 | #define IRCODE_ADAFRUIT_1 0x00FD08F7 // 16582903
110 | #define IRCODE_ADAFRUIT_2 0x00FD8877 // 16615543
111 | #define IRCODE_ADAFRUIT_3 0x00FD48B7 // 16599223
112 | #define IRCODE_ADAFRUIT_4 0x00FD28D7 // 16591063
113 | #define IRCODE_ADAFRUIT_5 0x00FDA857 // 16623703
114 | #define IRCODE_ADAFRUIT_6 0x00FD6897 // 16607383
115 | #define IRCODE_ADAFRUIT_7 0x00FD18E7 // 16586983
116 | #define IRCODE_ADAFRUIT_8 0x00FD9867 // 16619623
117 | #define IRCODE_ADAFRUIT_9 0x00FD58A7 // 16603303
118 |
119 | // IR Raw Key Codes for eTopxizu 44Key IR Remote Controller for 5050 3528 RGB LED Light Strip
120 | #define IRCODE_ETOPXIZU_HELD 0x7FFFFFFF // 4294967295
121 | #define IRCODE_ETOPXIZU_POWER 16712445
122 | #define IRCODE_ETOPXIZU_PLAY_PAUSE 16745085
123 | #define IRCODE_ETOPXIZU_BRIGHTNESS_UP 16726725
124 | #define IRCODE_ETOPXIZU_BRIGHTNESS_DOWN 16759365
125 |
126 | #define IRCODE_ETOPXIZU_DIY1 16724175
127 | #define IRCODE_ETOPXIZU_DIY2 16756815
128 | #define IRCODE_ETOPXIZU_DIY3 16740495
129 | #define IRCODE_ETOPXIZU_DIY4 16716015
130 | #define IRCODE_ETOPXIZU_DIY5 16748655
131 | #define IRCODE_ETOPXIZU_DIY6 16732335
132 |
133 | #define IRCODE_ETOPXIZU_JUMP3 16720095
134 | #define IRCODE_ETOPXIZU_JUMP7 16752735
135 | #define IRCODE_ETOPXIZU_FADE3 16736415
136 | #define IRCODE_ETOPXIZU_FADE7 16769055
137 | #define IRCODE_ETOPXIZU_FLASH 16764975
138 | #define IRCODE_ETOPXIZU_AUTO 16773135
139 |
140 | #define IRCODE_ETOPXIZU_QUICK 16771095
141 | #define IRCODE_ETOPXIZU_SLOW 16762935
142 |
143 | #define IRCODE_ETOPXIZU_RED_UP 16722135
144 | #define IRCODE_ETOPXIZU_RED_DOWN 16713975
145 |
146 | #define IRCODE_ETOPXIZU_GREEN_UP 16754775
147 | #define IRCODE_ETOPXIZU_GREEN_DOWN 16746615
148 |
149 | #define IRCODE_ETOPXIZU_BLUE_UP 16738455
150 | #define IRCODE_ETOPXIZU_BLUE_DOWN 16730295
151 |
152 | #define IRCODE_ETOPXIZU_RED 16718565
153 | #define IRCODE_ETOPXIZU_RED_ORANGE 16722645
154 | #define IRCODE_ETOPXIZU_ORANGE 16714485
155 | #define IRCODE_ETOPXIZU_YELLOW_ORANGE 16726215
156 | #define IRCODE_ETOPXIZU_YELLOW 16718055
157 |
158 | #define IRCODE_ETOPXIZU_GREEN 16751205
159 | #define IRCODE_ETOPXIZU_LIME 16755285
160 | #define IRCODE_ETOPXIZU_AQUA 16747125
161 | #define IRCODE_ETOPXIZU_TEAL 16758855
162 | #define IRCODE_ETOPXIZU_NAVY 16750695
163 |
164 | #define IRCODE_ETOPXIZU_BLUE 16753245
165 | #define IRCODE_ETOPXIZU_ROYAL_BLUE 16749165
166 | #define IRCODE_ETOPXIZU_PURPLE 16757325
167 | #define IRCODE_ETOPXIZU_INDIGO 16742535
168 | #define IRCODE_ETOPXIZU_MAGENTA 16734375
169 |
170 | #define IRCODE_ETOPXIZU_WHITE 16720605
171 | #define IRCODE_ETOPXIZU_PINK 16716525
172 | #define IRCODE_ETOPXIZU_LIGHT_PINK 16724685
173 | #define IRCODE_ETOPXIZU_BABY_BLUE 16775175
174 | #define IRCODE_ETOPXIZU_LIGHT_BLUE 16767015
175 |
176 | bool sparkfunRemoteEnabled = false;
177 | bool adafruitRemoteEnabled = true;
178 | bool etopxizuRemoteEnabled = true;
179 |
180 | // Low level IR code reading function
181 | // Function will return 0 if no IR code available
182 | unsigned long decodeIRCode() {
183 |
184 | decode_results results;
185 |
186 | results.value = 0;
187 |
188 | // Attempt to read an IR code ?
189 | if (irReceiver.decode(&results)) {
190 | delay(20);
191 |
192 | if (results.value != 0)
193 | // Serial.println(results.value);
194 |
195 | // Prepare to receive the next IR code
196 | irReceiver.resume();
197 | }
198 |
199 | return results.value;
200 | }
201 |
202 | // Read an IR code
203 | // Function will return 0 if no IR code available
204 | unsigned long readIRCode() {
205 |
206 | // Is there an IR code to read ?
207 | unsigned long code = decodeIRCode();
208 | if (code == 0) {
209 | // No code so return 0
210 | return 0;
211 | }
212 |
213 | // Keep reading until code changes
214 | while (decodeIRCode() == code) {
215 | ;
216 | }
217 | // Serial.println(code);
218 | return code;
219 | }
220 |
221 | unsigned long lastIrCode = 0;
222 |
223 | unsigned int holdStartTime = 0;
224 | unsigned int defaultHoldDelay = 500;
225 | bool isHolding = false;
226 |
227 | unsigned int zeroStartTime = 0;
228 | unsigned int zeroDelay = 120;
229 |
230 | unsigned long readIRCode(unsigned int holdDelay) {
231 | // read the raw code from the sensor
232 | unsigned long irCode = readIRCode();
233 |
234 | //Serial.print(millis());
235 | //Serial.print("\t");
236 | //Serial.println(irCode);
237 |
238 | // don't return a short click until we know it's not a long hold
239 | // we'll have to wait for holdDelay ms to pass before returning a non-zero IR code
240 | // then, after that delay, as long as the button is held, we can keep returning the code
241 | // every time until it's released
242 |
243 | // the ir remote only sends codes every 107 ms or so (avg 106.875, max 111, min 102),
244 | // so the ir sensor will return 0 even if a button is held
245 | // so we have to wait longer than that before returning a non-zero code
246 | // in order to detect that a button has been released and is no longer held
247 |
248 | // only reset after we've gotten 0 back for more than the ir remote send interval
249 | unsigned int zeroTime = 0;
250 |
251 | if (irCode == 0) {
252 | zeroTime = millis() - zeroStartTime;
253 | if (zeroTime >= zeroDelay && lastIrCode != 0) {
254 | //Serial.println(F("zero delay has elapsed, returning last ir code"));
255 | // the button has been released for longer than the zero delay
256 | // start over delays over and return the last code
257 | irCode = lastIrCode;
258 | lastIrCode = 0;
259 | return irCode;
260 | }
261 |
262 | return 0;
263 | }
264 |
265 | // reset the zero timer every time a non-zero code is read
266 | zeroStartTime = millis();
267 |
268 | unsigned int heldTime = 0;
269 |
270 | if (irCode == IRCODE_SPARKFUN_HELD || irCode == IRCODE_ADAFRUIT_HELD) {
271 | // has the hold delay passed?
272 | heldTime = millis() - holdStartTime;
273 | if (heldTime >= holdDelay) {
274 | isHolding = true;
275 | //Serial.println(F("hold delay has elapsed, returning last ir code"));
276 | return lastIrCode;
277 | }
278 | else if (holdStartTime == 0) {
279 | isHolding = false;
280 | holdStartTime = millis();
281 | }
282 | }
283 | else {
284 | // not zero, not IRCODE_SPARKFUN_HELD
285 | // store it for use later, until the hold and zero delays have elapsed
286 | holdStartTime = millis();
287 | isHolding = false;
288 | lastIrCode = irCode;
289 | return 0;
290 | }
291 |
292 | return 0;
293 | }
294 |
295 | void heldButtonHasBeenHandled() {
296 | lastIrCode = 0;
297 | isHolding = false;
298 | holdStartTime = 0;
299 | }
300 |
301 | unsigned long waitForIRCode() {
302 |
303 | unsigned long irCode = readIRCode();
304 | while ((irCode == 0) || (irCode == 0xFFFFFFFF)) {
305 | delay(200);
306 | irCode = readIRCode();
307 | }
308 | return irCode;
309 | }
310 |
311 | InputCommand getCommand(unsigned long input) {
312 | if (adafruitRemoteEnabled) {
313 | switch (input) {
314 | case IRCODE_ADAFRUIT_UP:
315 | return InputCommand::Up;
316 |
317 | case IRCODE_ADAFRUIT_DOWN:
318 | return InputCommand::Down;
319 |
320 | case IRCODE_ADAFRUIT_LEFT:
321 | return InputCommand::Left;
322 |
323 | case IRCODE_ADAFRUIT_RIGHT:
324 | return InputCommand::Right;
325 |
326 | case IRCODE_ADAFRUIT_ENTER_SAVE:
327 | return InputCommand::Select;
328 |
329 | case IRCODE_ADAFRUIT_STOP_MODE:
330 | case IRCODE_ADAFRUIT_1:
331 | return InputCommand::PlayMode;
332 |
333 | case IRCODE_ADAFRUIT_2:
334 | return InputCommand::CyclePalette;
335 |
336 | case IRCODE_ADAFRUIT_PLAY_PAUSE:
337 | return InputCommand::Power;
338 |
339 | case IRCODE_ADAFRUIT_VOLUME_UP:
340 | return InputCommand::BrightnessUp;
341 |
342 | case IRCODE_ADAFRUIT_VOLUME_DOWN:
343 | return InputCommand::BrightnessDown;
344 | }
345 | }
346 |
347 | if (sparkfunRemoteEnabled) {
348 | switch (input) {
349 | case IRCODE_SPARKFUN_UP:
350 | return InputCommand::Up;
351 |
352 | case IRCODE_SPARKFUN_DOWN:
353 | return InputCommand::Down;
354 |
355 | case IRCODE_SPARKFUN_LEFT:
356 | return InputCommand::Left;
357 |
358 | case IRCODE_SPARKFUN_RIGHT:
359 | return InputCommand::Right;
360 |
361 | case IRCODE_SPARKFUN_SELECT:
362 | return InputCommand::Select;
363 |
364 | case IRCODE_SPARKFUN_POWER:
365 | return InputCommand::Brightness;
366 |
367 | case IRCODE_SPARKFUN_A:
368 | return InputCommand::PlayMode;
369 |
370 | case IRCODE_SPARKFUN_B:
371 | return InputCommand::CyclePalette;
372 | }
373 | }
374 |
375 | if (etopxizuRemoteEnabled) {
376 | switch (input) {
377 | case IRCODE_ETOPXIZU_QUICK:
378 | return InputCommand::Up;
379 |
380 | case IRCODE_ETOPXIZU_SLOW:
381 | return InputCommand::Down;
382 |
383 | case IRCODE_ETOPXIZU_PLAY_PAUSE:
384 | return InputCommand::PlayMode;
385 |
386 | case IRCODE_ETOPXIZU_POWER:
387 | return InputCommand::Power;
388 |
389 | case IRCODE_ETOPXIZU_BRIGHTNESS_UP:
390 | return InputCommand::BrightnessUp;
391 | case IRCODE_ETOPXIZU_BRIGHTNESS_DOWN:
392 | return InputCommand::BrightnessDown;
393 |
394 | case IRCODE_ETOPXIZU_DIY1:
395 | return InputCommand::Pattern1;
396 | case IRCODE_ETOPXIZU_DIY2:
397 | return InputCommand::Pattern2;
398 | case IRCODE_ETOPXIZU_DIY3:
399 | return InputCommand::Pattern3;
400 | case IRCODE_ETOPXIZU_DIY4:
401 | return InputCommand::Pattern4;
402 | case IRCODE_ETOPXIZU_DIY5:
403 | return InputCommand::Pattern5;
404 | case IRCODE_ETOPXIZU_DIY6:
405 | return InputCommand::Pattern6;
406 | case IRCODE_ETOPXIZU_JUMP3:
407 | return InputCommand::Pattern7;
408 | case IRCODE_ETOPXIZU_JUMP7:
409 | return InputCommand::Pattern8;
410 | case IRCODE_ETOPXIZU_FADE3:
411 | return InputCommand::Pattern9;
412 | case IRCODE_ETOPXIZU_FADE7:
413 | return InputCommand::Pattern10;
414 |
415 | case IRCODE_ETOPXIZU_FLASH:
416 | return InputCommand::PreviousPalette;
417 | // return InputCommand::Pattern11;
418 |
419 | case IRCODE_ETOPXIZU_AUTO:
420 | return InputCommand::NextPalette;
421 | // return InputCommand::Pattern12;
422 |
423 | case IRCODE_ETOPXIZU_RED_UP:
424 | return InputCommand::RedUp;
425 | case IRCODE_ETOPXIZU_RED_DOWN:
426 | return InputCommand::RedDown;
427 |
428 | case IRCODE_ETOPXIZU_GREEN_UP:
429 | return InputCommand::GreenUp;
430 | case IRCODE_ETOPXIZU_GREEN_DOWN:
431 | return InputCommand::GreenDown;
432 |
433 | case IRCODE_ETOPXIZU_BLUE_UP:
434 | return InputCommand::BlueUp;
435 | case IRCODE_ETOPXIZU_BLUE_DOWN:
436 | return InputCommand::BlueDown;
437 |
438 | case IRCODE_ETOPXIZU_RED:
439 | return InputCommand::Red;
440 | case IRCODE_ETOPXIZU_RED_ORANGE:
441 | return InputCommand::RedOrange;
442 | case IRCODE_ETOPXIZU_ORANGE:
443 | return InputCommand::Orange;
444 | case IRCODE_ETOPXIZU_YELLOW_ORANGE:
445 | return InputCommand::YellowOrange;
446 | case IRCODE_ETOPXIZU_YELLOW:
447 | return InputCommand::Yellow;
448 |
449 | case IRCODE_ETOPXIZU_GREEN:
450 | return InputCommand::Green;
451 | case IRCODE_ETOPXIZU_LIME:
452 | return InputCommand::Lime;
453 | case IRCODE_ETOPXIZU_AQUA:
454 | return InputCommand::Aqua;
455 | case IRCODE_ETOPXIZU_TEAL:
456 | return InputCommand::Teal;
457 | case IRCODE_ETOPXIZU_NAVY:
458 | return InputCommand::Navy;
459 |
460 | case IRCODE_ETOPXIZU_BLUE:
461 | return InputCommand::Blue;
462 | case IRCODE_ETOPXIZU_ROYAL_BLUE:
463 | return InputCommand::RoyalBlue;
464 | case IRCODE_ETOPXIZU_PURPLE:
465 | return InputCommand::Purple;
466 | case IRCODE_ETOPXIZU_INDIGO:
467 | return InputCommand::Indigo;
468 | case IRCODE_ETOPXIZU_MAGENTA:
469 | return InputCommand::Magenta;
470 |
471 | case IRCODE_ETOPXIZU_WHITE:
472 | return InputCommand::White;
473 | case IRCODE_ETOPXIZU_PINK:
474 | return InputCommand::Pink;
475 | case IRCODE_ETOPXIZU_LIGHT_PINK:
476 | return InputCommand::LightPink;
477 | case IRCODE_ETOPXIZU_BABY_BLUE:
478 | return InputCommand::BabyBlue;
479 | case IRCODE_ETOPXIZU_LIGHT_BLUE:
480 | return InputCommand::LightBlue;
481 | }
482 | }
483 |
484 | return InputCommand::None;
485 | }
486 |
487 | InputCommand readCommand() {
488 | return getCommand(readIRCode());
489 | }
490 |
491 | InputCommand readCommand(unsigned int holdDelay) {
492 | return getCommand(readIRCode(holdDelay));
493 | }
494 |
495 | #endif
496 |
--------------------------------------------------------------------------------
/Drawing.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Torch: https://github.com/evilgeniuslabs/torch
3 | * Copyright (C) 2015 Jason Coon
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | void drawCircle(int16_t x0, int16_t y0, uint16_t radius, const CRGB& color)
20 | {
21 | int a = radius, b = 0;
22 | int radiusError = 1 - a;
23 |
24 | if (radius == 0) {
25 | leds[XY(x0, y0)] = color;
26 | return;
27 | }
28 |
29 | while (a >= b)
30 | {
31 | leds[XY(a + x0, b + y0)] = color;
32 | leds[XY(b + x0, a + y0)] = color;
33 | leds[XY(-a + x0, b + y0)] = color;
34 | leds[XY(-b + x0, a + y0)] = color;
35 | leds[XY(-a + x0, -b + y0)] = color;
36 | leds[XY(-b + x0, -a + y0)] = color;
37 | leds[XY(a + x0, -b + y0)] = color;
38 | leds[XY(b + x0, -a + y0)] = color;
39 |
40 | b++;
41 | if (radiusError < 0)
42 | radiusError += 2 * b + 1;
43 | else
44 | {
45 | a--;
46 | radiusError += 2 * (b - a + 1);
47 | }
48 | }
49 | }
50 |
51 | void drawFastVLine(uint16_t x, uint16_t y0, uint16_t y1, const CRGB& color) {
52 | uint16_t i;
53 |
54 | for (i = y0; i <= y1; i++) {
55 | leds[XY(x, i)] = color;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Effects.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Torch: https://github.com/evilgeniuslabs/torch
3 | * Copyright (C) 2015 Jason Coon
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | // give it a linear tail to the right
20 | void streamRight(byte scale, int fromX = 0, int toX = MATRIX_WIDTH, int fromY = 0, int toY = MATRIX_HEIGHT)
21 | {
22 | for (int x = fromX + 1; x < toX; x++) {
23 | for (int y = fromY; y < toY; y++) {
24 | leds[XY(x, y)] += leds[XY(x - 1, y)];
25 | leds[XY(x, y)].nscale8(scale);
26 | }
27 | }
28 | for (int y = fromY; y < toY; y++)
29 | leds[XY(0, y)].nscale8(scale);
30 | }
31 |
32 | // give it a linear tail to the left
33 | void streamLeft(byte scale, int fromX = MATRIX_WIDTH, int toX = 0, int fromY = 0, int toY = MATRIX_HEIGHT)
34 | {
35 | for (int x = toX; x < fromX; x++) {
36 | for (int y = fromY; y < toY; y++) {
37 | leds[XY(x, y)] += leds[XY(x + 1, y)];
38 | leds[XY(x, y)].nscale8(scale);
39 | }
40 | }
41 | for (int y = fromY; y < toY; y++)
42 | leds[XY(0, y)].nscale8(scale);
43 | }
44 |
45 | // give it a linear tail downwards
46 | void streamDown(byte scale)
47 | {
48 | for (int x = 0; x < MATRIX_WIDTH; x++) {
49 | for (int y = 1; y < MATRIX_HEIGHT; y++) {
50 | leds[XY(x, y)] += leds[XY(x, y - 1)];
51 | leds[XY(x, y)].nscale8(scale);
52 | }
53 | }
54 | for (int x = 0; x < MATRIX_WIDTH; x++)
55 | leds[XY(x, 0)].nscale8(scale);
56 | }
57 |
58 | // give it a linear tail upwards
59 | void streamUp(byte scale)
60 | {
61 | for (int x = 0; x < MATRIX_WIDTH; x++) {
62 | for (int y = MATRIX_HEIGHT - 2; y >= 0; y--) {
63 | leds[XY(x, y)] += leds[XY(x, y + 1)];
64 | leds[XY(x, y)].nscale8(scale);
65 | }
66 | }
67 | for (int x = 0; x < MATRIX_WIDTH; x++)
68 | leds[XY(x, MATRIX_HEIGHT - 1)].nscale8(scale);
69 | }
70 |
71 | // give it a linear tail up and to the left
72 | void streamUpAndLeft(byte scale)
73 | {
74 | for (int x = 0; x < MATRIX_WIDTH - 1; x++) {
75 | for (int y = MATRIX_HEIGHT - 2; y >= 0; y--) {
76 | leds[XY(x, y)] += leds[XY(x + 1, y + 1)];
77 | leds[XY(x, y)].nscale8(scale);
78 | }
79 | }
80 | for (int x = 0; x < MATRIX_WIDTH; x++)
81 | leds[XY(x, MATRIX_HEIGHT - 1)].nscale8(scale);
82 | for (int y = 0; y < MATRIX_HEIGHT; y++)
83 | leds[XY(MATRIX_WIDTH - 1, y)].nscale8(scale);
84 | }
85 |
86 | // give it a linear tail up and to the right
87 | void streamUpAndRight(byte scale)
88 | {
89 | for (int x = 0; x < MATRIX_WIDTH - 1; x++) {
90 | for (int y = MATRIX_HEIGHT - 2; y >= 0; y--) {
91 | leds[XY(x + 1, y)] += leds[XY(x, y + 1)];
92 | leds[XY(x, y)].nscale8(scale);
93 | }
94 | }
95 | // fade the bottom row
96 | for (int x = 0; x < MATRIX_WIDTH; x++)
97 | leds[XY(x, MATRIX_HEIGHT - 1)].nscale8(scale);
98 |
99 | // fade the right column
100 | for (int y = 0; y < MATRIX_HEIGHT; y++)
101 | leds[XY(MATRIX_WIDTH - 1, y)].nscale8(scale);
102 | }
103 |
104 | void moveUp()
105 | {
106 | for (int y = 0; y < MATRIX_HEIGHT - 1; y++) {
107 | for (int x = 0; x < MATRIX_WIDTH; x++) {
108 | leds[XY(x, y)] = leds[XY(x, y + 1)];
109 | }
110 | }
111 | }
112 |
113 | void moveDown() {
114 | for (int y = MATRIX_HEIGHT - 1; y > 0; y--) {
115 | for (int x = 0; x < MATRIX_WIDTH; x++) {
116 | leds[XY(x, y)] = leds[XY(x, y - 1)];
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/Fire2012Rainbow.h:
--------------------------------------------------------------------------------
1 | // Fire2012 with programmable Color Palette
2 | // by Mark Kriegsman: https://github.com/FastLED/FastLED/blob/master/examples/Fire2012WithPalette/Fire2012WithPalette.ino
3 | //
4 | // This code is the same fire simulation as the original "Fire2012",
5 | // but each heat cell's temperature is translated to color through a FastLED
6 | // programmable color palette, instead of through the "HeatColor(...)" function.
7 | //
8 | // Four different static color palettes are provided here, plus one dynamic one.
9 | //
10 | // The three static ones are:
11 | // 1. the FastLED built-in HeatColors_p -- this is the default, and it looks
12 | // pretty much exactly like the original Fire2012.
13 | //
14 | // To use any of the other palettes below, just "uncomment" the corresponding code.
15 | //
16 | // 2. a gradient from black to red to yellow to white, which is
17 | // visually similar to the HeatColors_p, and helps to illustrate
18 | // what the 'heat colors' palette is actually doing,
19 | // 3. a similar gradient, but in blue colors rather than red ones,
20 | // i.e. from black to blue to aqua to white, which results in
21 | // an "icy blue" fire effect,
22 | // 4. a simplified three-step gradient, from black to red to white, just to show
23 | // that these gradients need not have four components; two or
24 | // three are possible, too, even if they don't look quite as nice for fire.
25 | //
26 | // The dynamic palette shows how you can change the basic 'hue' of the
27 | // color palette every time through the loop, producing "rainbow fire".
28 |
29 | // Fire2012 by Mark Kriegsman, July 2012
30 | // as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY
31 | ////
32 | // This basic one-dimensional 'fire' simulation works roughly as follows:
33 | // There's a underlying array of 'heat' cells, that model the temperature
34 | // at each point along the line. Every cycle through the simulation,
35 | // four steps are performed:
36 | // 1) All cells cool down a little bit, losing heat to the air
37 | // 2) The heat from each cell drifts 'up' and diffuses a little
38 | // 3) Sometimes randomly new 'sparks' of heat are added at the bottom
39 | // 4) The heat from each cell is rendered as a color into the leds array
40 | // The heat-to-color mapping uses a black-body radiation approximation.
41 | //
42 | // Temperature is in arbitrary units from 0 (cold black) to 255 (white hot).
43 | //
44 | // This simulation scales it self a bit depending on MATRIX_HEIGHT; it should look
45 | // "OK" on anywhere from 20 to 100 LEDs without too much tweaking.
46 | //
47 | // I recommend running this simulation at anywhere from 30-100 frames per second,
48 | // meaning an interframe delay of about 10-35 milliseconds.
49 | //
50 | // Looks best on a high-density LED setup (60+ pixels/meter).
51 | //
52 | //
53 | // There are two main parameters you can play with to control the look and
54 | // feel of your fire: COOLING (used in step 1 above), and SPARKING (used
55 | // in step 3 above).
56 | //
57 | // COOLING: How much does the air cool as it rises?
58 | // Less cooling = taller flames. More cooling = shorter flames.
59 | // Default 55, suggested range 20-100
60 | #define COOLINGRainbow 80 // 100 // 55 // 86
61 |
62 | // SPARKING: What chance (out of 255) is there that a new spark will be lit?
63 | // Higher chance = more roaring fire. Lower chance = more flickery fire.
64 | // Default 120, suggested range 50-200.
65 | #define SPARKINGRainbow 130 // 30 // 120 // 90 // 60
66 | uint16_t Fire2012Rainbow1()
67 | {
68 | // Array of temperature readings at each simulation cell
69 | static byte heat[MATRIX_WIDTH][MATRIX_HEIGHT];
70 |
71 | for(uint8_t x = 0; x < MATRIX_WIDTH; x++) {
72 | // Step 1. Cool down every cell a little
73 | for (int i = 0; i < MATRIX_HEIGHT; i++) {
74 | heat[x][i] = qsub8(heat[x][i], random8(0, ((COOLINGRainbow * 10) / MATRIX_HEIGHT) + 2));
75 | }
76 |
77 | // Step 2. Heat from each cell drifts 'up' and diffuses a little
78 | for (int k = MATRIX_HEIGHT - 1; k >= 2; k--) {
79 | heat[x][k] = (heat[x][k - 1] + heat[x][k - 2] + heat[x][k - 2]) / 3;
80 | }
81 |
82 | // Step 3. Randomly ignite new 'sparks' of heat near the bottom
83 | if (random8() < SPARKINGRainbow) {
84 | int y = random8(2);
85 | heat[x][y] = qadd8(heat[x][y], random8(160, 255));
86 | }
87 |
88 | // Step 4. Map from heat cells to LED colors
89 | for (int j = 0; j < MATRIX_HEIGHT; j++) {
90 | // Scale the heat value from 0-255 down to 0-240
91 | // for best results with color palettes.
92 | byte colorindex = scale8(heat[x][j], 160);
93 | leds[XY(x, (MATRIX_HEIGHT - 1) - j)] = ColorFromPalette(RainbowColors_p, colorindex);
94 | }
95 | }
96 |
97 | return 15;
98 | }
99 |
--------------------------------------------------------------------------------
/Fire2012WithPalette.h:
--------------------------------------------------------------------------------
1 | // Fire2012 with programmable Color Palette
2 | // by Mark Kriegsman: https://github.com/FastLED/FastLED/blob/master/examples/Fire2012WithPalette/Fire2012WithPalette.ino
3 | //
4 | // This code is the same fire simulation as the original "Fire2012",
5 | // but each heat cell's temperature is translated to color through a FastLED
6 | // programmable color palette, instead of through the "HeatColor(...)" function.
7 | //
8 | // Four different static color palettes are provided here, plus one dynamic one.
9 | //
10 | // The three static ones are:
11 | // 1. the FastLED built-in HeatColors_p -- this is the default, and it looks
12 | // pretty much exactly like the original Fire2012.
13 | //
14 | // To use any of the other palettes below, just "uncomment" the corresponding code.
15 | //
16 | // 2. a gradient from black to red to yellow to white, which is
17 | // visually similar to the HeatColors_p, and helps to illustrate
18 | // what the 'heat colors' palette is actually doing,
19 | // 3. a similar gradient, but in blue colors rather than red ones,
20 | // i.e. from black to blue to aqua to white, which results in
21 | // an "icy blue" fire effect,
22 | // 4. a simplified three-step gradient, from black to red to white, just to show
23 | // that these gradients need not have four components; two or
24 | // three are possible, too, even if they don't look quite as nice for fire.
25 | //
26 | // The dynamic palette shows how you can change the basic 'hue' of the
27 | // color palette every time through the loop, producing "rainbow fire".
28 |
29 | // Fire2012 by Mark Kriegsman, July 2012
30 | // as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY
31 | ////
32 | // This basic one-dimensional 'fire' simulation works roughly as follows:
33 | // There's a underlying array of 'heat' cells, that model the temperature
34 | // at each point along the line. Every cycle through the simulation,
35 | // four steps are performed:
36 | // 1) All cells cool down a little bit, losing heat to the air
37 | // 2) The heat from each cell drifts 'up' and diffuses a little
38 | // 3) Sometimes randomly new 'sparks' of heat are added at the bottom
39 | // 4) The heat from each cell is rendered as a color into the leds array
40 | // The heat-to-color mapping uses a black-body radiation approximation.
41 | //
42 | // Temperature is in arbitrary units from 0 (cold black) to 255 (white hot).
43 | //
44 | // This simulation scales it self a bit depending on MATRIX_HEIGHT; it should look
45 | // "OK" on anywhere from 20 to 100 LEDs without too much tweaking.
46 | //
47 | // I recommend running this simulation at anywhere from 30-100 frames per second,
48 | // meaning an interframe delay of about 10-35 milliseconds.
49 | //
50 | // Looks best on a high-density LED setup (60+ pixels/meter).
51 | //
52 | //
53 | // There are two main parameters you can play with to control the look and
54 | // feel of your fire: COOLING (used in step 1 above), and SPARKING (used
55 | // in step 3 above).
56 | //
57 | // COOLING: How much does the air cool as it rises?
58 | // Less cooling = taller flames. More cooling = shorter flames.
59 | // Default 55, suggested range 20-100
60 | #define COOLING 200 // 100 // 55 // 86
61 |
62 | // SPARKING: What chance (out of 255) is there that a new spark will be lit?
63 | // Higher chance = more roaring fire. Lower chance = more flickery fire.
64 | // Default 120, suggested range 50-200.
65 | #define SPARKING 230 // 30 // 120 // 90 // 60
66 |
67 | uint16_t Fire2012WithPalette()
68 | {
69 | // Array of temperature readings at each simulation cell
70 | static byte heat[MATRIX_WIDTH][MATRIX_HEIGHT];
71 |
72 | for(uint8_t x = 0; x < MATRIX_WIDTH; x++) {
73 | // Step 1. Cool down every cell a little
74 | for (int i = 0; i < MATRIX_HEIGHT; i++) {
75 | heat[x][i] = qsub8(heat[x][i], random8(0, ((COOLING * 10) / MATRIX_HEIGHT) + 2));
76 | }
77 |
78 | // Step 2. Heat from each cell drifts 'up' and diffuses a little
79 | for (int k = MATRIX_HEIGHT - 1; k >= 2; k--) {
80 | heat[x][k] = (heat[x][k - 1] + heat[x][k - 2] + heat[x][k - 2]) / 3;
81 | }
82 |
83 | // Step 3. Randomly ignite new 'sparks' of heat near the bottom
84 | if (random8() < SPARKING) {
85 | int y = random8(2);
86 | heat[x][y] = qadd8(heat[x][y], random8(160, 255));
87 | }
88 |
89 | // Step 4. Map from heat cells to LED colors
90 | for (int j = 0; j < MATRIX_HEIGHT; j++) {
91 | // Scale the heat value from 0-255 down to 0-240
92 | // for best results with color palettes.
93 | byte colorindex = scale8(heat[x][j], 160);
94 | leds[XY(x, (MATRIX_HEIGHT - 1) - j)] = ColorFromPalette(HeatColors_p, colorindex);
95 | }
96 | }
97 |
98 | return 15;
99 | }
100 |
--------------------------------------------------------------------------------
/FireBlue.h:
--------------------------------------------------------------------------------
1 | // Slightly modified version of the fire pattern from MessageTorch by Lukas Zeller:
2 | // https://github.com/plan44/messagetorch
3 |
4 | // The MIT License (MIT)
5 |
6 | // Copyright (c) 2014 Lukas Zeller
7 |
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
9 | // this software and associated documentation files (the "Software"), to deal in
10 | // the Software without restriction, including without limitation the rights to
11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12 | // the Software, and to permit persons to whom the Software is furnished to do so,
13 | // subject to the following conditions:
14 |
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 |
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
25 | // torch parameters
26 |
27 | uint16_t cycle_wait2 = 1; // 0..255
28 |
29 | byte flame_min2 = 100; // 0..255
30 | byte flame_max2 = 220; // 0..255
31 |
32 | byte random_spark_probability2 = 2; // 0..100
33 | byte spark_min2 = 200; // 0..255
34 | byte spark_max2 = 255; // 0..255
35 |
36 | byte spark_tfr2 = 40; // 0..256 how much energy is transferred up for a spark per cycle
37 | uint16_t spark_cap2 = 200; // 0..255: spark cells: how much energy is retained from previous cycle
38 |
39 | uint16_t up_rad2 = 40; // up radiation
40 | uint16_t side_rad2 = 35; // sidewards radiation
41 | uint16_t heat_cap2 = 0; // 0..255: passive cells: how much energy is retained from previous cycle
42 |
43 | byte red_bg2 = 0;
44 | byte green_bg2 = 0; //0
45 | byte blue_bg2 = 0;
46 | byte red_bias2 = 0; //10
47 | byte green_bias2 = 0;
48 | byte blue_bias2 = 10;
49 | int red_energy2 = 0; //180
50 | int green_energy2 = 0; // 80;
51 | int blue_energy2 = 220;
52 |
53 | byte upside_down2 = 0; // if set, flame (or rather: drop) animation is upside down. Text remains as-is
54 |
55 | // torch mode
56 | // ==========
57 |
58 | #define numLeds NUM_LEDS
59 | #define ledsPerLevel MATRIX_WIDTH
60 | #define levels MATRIX_HEIGHT
61 |
62 | byte currentEnergy2[numLeds]; // current energy level
63 | byte nextEnergy2[numLeds]; // next energy level
64 | byte energyMode2[numLeds]; // mode how energy is calculated for this point
65 |
66 | enum {
67 | torch_passive2 = 0, // just environment, glow from nearby radiation
68 | torch_nop2 = 1, // no processing
69 | torch_spark2= 2, // slowly looses energy, moves up
70 | torch_spark2_temp = 3, // a spark still getting energy from the level below
71 | };
72 |
73 | inline void reduce2(byte &aByte, byte aAmount, byte aMin = 0)
74 | {
75 | int r = aByte-aAmount;
76 | if (raMax)
87 | aByte = aMax;
88 | else
89 | aByte = (byte)r;
90 | }
91 |
92 | uint16_t randomBlue(uint16_t aMinOrMax, uint16_t aMax = 0)
93 | {
94 | if (aMax==0) {
95 | aMax = aMinOrMax;
96 | aMinOrMax = 0;
97 | }
98 | uint32_t r = aMinOrMax;
99 | aMax = aMax - aMinOrMax + 1;
100 | r += rand() % aMax;
101 | return r;
102 | }
103 |
104 | void resetEnergy2()
105 | {
106 | for (int i=0; i>8;
140 | // this cell becomes active spark
141 | energyMode2[i] = torch_spark2;
142 | }
143 | else {
144 | increase2(e, spark_tfr2);
145 | }
146 | break;
147 | }
148 | case torch_passive: {
149 | e = ((int)e*heat_cap2)>>8;
150 | increase2(e, ((((int)currentEnergy2[i-1]+(int)currentEnergy2[i+1])*side_rad2)>>9) + (((int)currentEnergy2[i-ledsPerLevel]*up_rad2)>>8));
151 | }
152 | default:
153 | break;
154 | }
155 | nextEnergy2[i++] = e;
156 | }
157 | }
158 | }
159 |
160 | const uint8_t energymap2[32] = {0, 64, 96, 112, 128, 144, 152, 160, 168, 176, 184, 184, 192, 200, 200, 208, 208, 216, 216, 224, 224, 224, 232, 232, 232, 240, 240, 240, 240, 248, 248, 248};
161 |
162 | void calcNextColors2()
163 | {
164 | for (int i=0; i250)
173 | leds[i] = CRGB(170, 170, e); // blueish extra-bright spark
174 | else {
175 | if (e>0) {
176 | // energy to brightness is non-linear
177 | byte eb = energymap[e>>3];
178 | byte r = red_bias2;
179 | byte g = green_bias2;
180 | byte b = blue_bias2;
181 | increase2(r, (eb*red_energy2)>>8);
182 | increase2(g, (eb*green_energy2)>>8);
183 | increase2(b, (eb*blue_energy2)>>8);
184 | leds[i] = CRGB(r, g, b);
185 | }
186 | else {
187 | // background, no energy
188 | leds[i] = CRGB(red_bg2, green_bg2, blue_bg2);
189 | }
190 | }
191 | }
192 | }
193 |
194 | void injectRandom2()
195 | {
196 | // random flame energy at bottom row
197 | for (int i=0; iaMax)
83 | aByte = aMax;
84 | else
85 | aByte = (byte)r;
86 | }
87 |
88 | uint16_t randomChemicalFire(uint16_t aMinOrMax, uint16_t aMax = 0) // not really sure if this is needed at this stage
89 | {
90 | if (aMax==0) {
91 | aMax = aMinOrMax;
92 | aMinOrMax = 0;
93 | }
94 | uint32_t r = aMinOrMax;
95 | aMax = aMax - aMinOrMax + 1;
96 | r += rand() % aMax;
97 | return r;
98 | }
99 |
100 | void resetEnergy6()
101 | {
102 | for (int i=0; i>8;
136 | // this cell becomes active spark
137 | energyModeChemicalFire[i] = torch_sparkChemicalFire;
138 | }
139 | else {
140 | increaseChemicalFire(e, spark_tfrChemicalFire);
141 | }
142 | break;
143 | }
144 | case torch_passive: {
145 | e = ((int)e*heat_capChemicalFire)>>8;
146 | increaseChemicalFire(e, ((((int)currentEnergyChemicalFire[i-1]+(int)currentEnergyChemicalFire[i+1])*side_radChemicalFire)>>9) + (((int)currentEnergyChemicalFire[i-ledsPerLevel]*up_radChemicalFire)>>8));
147 | }
148 | default:
149 | break;
150 | }
151 | nextEnergyChemicalFire[i++] = e;
152 | }
153 | }
154 | }
155 |
156 | const uint8_t energymapChemicalFire[32] = {0, 64, 96, 112, 128, 144, 152, 160, 168, 176, 184, 184, 192, 200, 200, 208, 208, 216, 216, 224, 224, 224, 232, 232, 232, 240, 240, 240, 240, 248, 248, 248};
157 |
158 | void calcNextColorsChemicalFire()
159 | {
160 | for (int i=0; i250)
169 | leds[i] = CRGB(170, 170, e); // blueish extra-bright spark
170 | else {
171 | if (e>0) {
172 | // energy to brightness is non-linear
173 | byte eb = energymap[e>>3];
174 | byte r = red_biasChemicalFire;
175 | byte g = green_biasChemicalFire;
176 | byte b = blue_biasChemicalFire;
177 | increaseChemicalFire(r, (eb*red_energyChemicalFire)>>8);
178 | increaseChemicalFire(g, (eb*green_energyChemicalFire)>>8);
179 | increaseChemicalFire(b, (eb*blue_energyChemicalFire)>>8);
180 | leds[i] = CRGB(r, g, b);
181 | }
182 | else {
183 | // background, no energy
184 | leds[i] = CRGB(red_bgChemicalFire, green_bgChemicalFire, blue_bgChemicalFire);
185 | }
186 | }
187 | }
188 | }
189 |
190 | void injectRandomChemicalFire()
191 | {
192 | // random flame energy at bottom row
193 | for (int i=0; iaMax)
59 | aByte = aMax;
60 | else
61 | aByte = (byte)r;
62 | }
63 |
64 | uint16_t randomCustom6(uint16_t aMinOrMax, uint16_t aMax = 0)
65 | {
66 | if (aMax==0) {
67 | aMax = aMinOrMax;
68 | aMinOrMax = 0;
69 | }
70 | uint32_t r = aMinOrMax;
71 | aMax = aMax - aMinOrMax + 1;
72 | r += rand() % aMax;
73 | return r;
74 | }
75 |
76 | void resetEnergyCustom6()
77 | {
78 | for (int i=0; i>8;
112 | // this cell becomes active spark
113 | energyModeCustom6[i] = torch_sparkCustom6;
114 | }
115 | else {
116 | increaseCustom6(e, spark_tfrCustom6);
117 | }
118 | break;
119 | }
120 | case torch_passive: {
121 | e = ((int)e*heat_capCustom6)>>8;
122 | increaseCustom6(e, ((((int)currentEnergyCustom6[i-1]+(int)currentEnergyCustom6[i+1])*side_radCustom6)>>9) + (((int)currentEnergyCustom6[i-ledsPerLevel]*up_radCustom6)>>8));
123 | }
124 | default:
125 | break;
126 | }
127 | nextEnergyCustom6[i++] = e;
128 | }
129 | }
130 | }
131 |
132 | const uint8_t energymapCustom6[32] = {0, 64, 96, 112, 128, 144, 152, 160, 168, 176, 184, 184, 192, 200, 200, 208, 208, 216, 216, 224, 224, 224, 232, 232, 232, 240, 240, 240, 240, 248, 248, 248};
133 |
134 | void calcNextColorsCustom6()
135 | {
136 | for (int i=0; i250)
145 | leds[i] = CRGB(170, 170, e); // blueish extra-bright spark
146 | else {
147 | if (e>0) {
148 | // energy to brightness is non-linear
149 | byte eb = energymap[e>>3];
150 | byte r = red_biasCustom6;
151 | byte g = green_biasCustom6;
152 | byte b = blue_biasCustom6;
153 | increaseCustom6(r, (eb*red_energyCustom6)>>8);
154 | increaseCustom6(g, (eb*green_energyCustom6)>>8);
155 | increaseCustom6(b, (eb*blue_energyCustom6)>>8);
156 | leds[i] = CRGB(r, g, b);
157 | }
158 | else {
159 | // background, no energy
160 | leds[i] = CRGB(red_bgCustom6, green_bgCustom6, blue_bgCustom6);
161 | }
162 | }
163 | }
164 | }
165 |
166 | void injectRandomCustom6()
167 | {
168 | // random flame energy at bottom row
169 | for (int i=0; iaMax)
87 | aByte = aMax;
88 | else
89 | aByte = (byte)r;
90 | }
91 |
92 | uint16_t randomGreen(uint16_t aMinOrMax, uint16_t aMax = 0)
93 | {
94 | if (aMax==0) {
95 | aMax = aMinOrMax;
96 | aMinOrMax = 0;
97 | }
98 | uint32_t r = aMinOrMax;
99 | aMax = aMax - aMinOrMax + 1;
100 | r += rand() % aMax;
101 | return r;
102 | }
103 |
104 | void resetEnergy3()
105 | {
106 | for (int i=0; i>8;
140 | // this cell becomes active spark
141 | energyMode3[i] = torch_spark3;
142 | }
143 | else {
144 | increase3(e, spark_tfr3);
145 | }
146 | break;
147 | }
148 | case torch_passive: {
149 | e = ((int)e*heat_cap3)>>8;
150 | increase3(e, ((((int)currentEnergy3[i-1]+(int)currentEnergy3[i+1])*side_rad3)>>9) + (((int)currentEnergy3[i-ledsPerLevel]*up_rad3)>>8));
151 | }
152 | default:
153 | break;
154 | }
155 | nextEnergy3[i++] = e;
156 | }
157 | }
158 | }
159 |
160 | const uint8_t energymap3[32] = {0, 64, 96, 112, 128, 144, 152, 160, 168, 176, 184, 184, 192, 200, 200, 208, 208, 216, 216, 224, 224, 224, 232, 232, 232, 240, 240, 240, 240, 248, 248, 248};
161 |
162 | void calcNextColors3()
163 | {
164 | for (int i=0; i250)
173 | leds[i] = CRGB(170, 170, e); // blueish extra-bright spark
174 | else {
175 | if (e>0) {
176 | // energy to brightness is non-linear
177 | byte eb = energymap[e>>3];
178 | byte r = red_bias3;
179 | byte g = green_bias3;
180 | byte b = blue_bias3;
181 | increase3(r, (eb*red_energy3)>>8);
182 | increase3(g, (eb*green_energy3)>>8);
183 | increase3(b, (eb*blue_energy3)>>8);
184 | leds[i] = CRGB(r, g, b);
185 | }
186 | else {
187 | // background, no energy
188 | leds[i] = CRGB(red_bg3, green_bg3, blue_bg3);
189 | }
190 | }
191 | }
192 | }
193 |
194 | void injectRandom3()
195 | {
196 | // random flame energy at bottom row
197 | for (int i=0; iaMax)
83 | aByte = aMax;
84 | else
85 | aByte = (byte)r;
86 | }
87 |
88 | uint16_t random6(uint16_t aMinOrMax, uint16_t aMax = 0)
89 | {
90 | if (aMax==0) {
91 | aMax = aMinOrMax;
92 | aMinOrMax = 0;
93 | }
94 | uint32_t r = aMinOrMax;
95 | aMax = aMax - aMinOrMax + 1;
96 | r += rand() % aMax;
97 | return r;
98 | }
99 |
100 | void resetEnergy5()
101 | {
102 | for (int i=0; i>8;
136 | // this cell becomes active spark
137 | energyMode5[i] = torch_spark5;
138 | }
139 | else {
140 | increase5(e, spark_tfr5);
141 | }
142 | break;
143 | }
144 | case torch_passive: {
145 | e = ((int)e*heat_cap5)>>8;
146 | increase5(e, ((((int)currentEnergy5[i-1]+(int)currentEnergy5[i+1])*side_rad5)>>9) + (((int)currentEnergy5[i-ledsPerLevel]*up_rad5)>>8));
147 | }
148 | default:
149 | break;
150 | }
151 | nextEnergy5[i++] = e;
152 | }
153 | }
154 | }
155 |
156 | const uint8_t energymap5[32] = {0, 64, 96, 112, 128, 144, 152, 160, 168, 176, 184, 184, 192, 200, 200, 208, 208, 216, 216, 224, 224, 224, 232, 232, 232, 240, 240, 240, 240, 248, 248, 248};
157 |
158 | void calcNextColors5()
159 | {
160 | for (int i=0; i250)
169 | leds[i] = CRGB(170, 170, e); // blueish extra-bright spark
170 | else {
171 | if (e>0) {
172 | // energy to brightness is non-linear
173 | byte eb = energymap[e>>3];
174 | byte r = red_bias5;
175 | byte g = green_bias5;
176 | byte b = blue_bias5;
177 | increase5(r, (eb*red_energy5)>>8);
178 | increase5(g, (eb*green_energy5)>>8);
179 | increase5(b, (eb*blue_energy5)>>8);
180 | leds[i] = CRGB(r, g, b);
181 | }
182 | else {
183 | // background, no energy
184 | leds[i] = CRGB(red_bg5, green_bg5, blue_bg5);
185 | }
186 | }
187 | }
188 | }
189 |
190 | void injectRandom5()
191 | {
192 | // random flame energy at bottom row
193 | for (int i=0; iaMax)
87 | aByte = aMax;
88 | else
89 | aByte = (byte)r;
90 | }
91 |
92 | uint16_t random5(uint16_t aMinOrMax, uint16_t aMax = 0)
93 | {
94 | if (aMax==0) {
95 | aMax = aMinOrMax;
96 | aMinOrMax = 0;
97 | }
98 | uint32_t r = aMinOrMax;
99 | aMax = aMax - aMinOrMax + 1;
100 | r += rand() % aMax;
101 | return r;
102 | }
103 |
104 | void resetEnergy4()
105 | {
106 | for (int i=0; i>8;
140 | // this cell becomes active spark
141 | energyMode4[i] = torch_spark4;
142 | }
143 | else {
144 | increase4(e, spark_tfr4);
145 | }
146 | break;
147 | }
148 | case torch_passive: {
149 | e = ((int)e*heat_cap4)>>8;
150 | increase4(e, ((((int)currentEnergy4[i-1]+(int)currentEnergy4[i+1])*side_rad4)>>9) + (((int)currentEnergy4[i-ledsPerLevel]*up_rad4)>>8));
151 | }
152 | default:
153 | break;
154 | }
155 | nextEnergy4[i++] = e;
156 | }
157 | }
158 | }
159 |
160 | const uint8_t energymap4[32] = {0, 64, 96, 112, 128, 144, 152, 160, 168, 176, 184, 184, 192, 200, 200, 208, 208, 216, 216, 224, 224, 224, 232, 232, 232, 240, 240, 240, 240, 248, 248, 248};
161 |
162 | void calcNextColors4()
163 | {
164 | for (int i=0; i250)
173 | leds[i] = CRGB(170, 170, e); // blueish extra-bright spark
174 | else {
175 | if (e>0) {
176 | // energy to brightness is non-linear
177 | byte eb = energymap[e>>3];
178 | byte r = red_bias4;
179 | byte g = green_bias4;
180 | byte b = blue_bias4;
181 | increase4(r, (eb*red_energy4)>>8);
182 | increase4(g, (eb*green_energy4)>>8);
183 | increase4(b, (eb*blue_energy4)>>8);
184 | leds[i] = CRGB(r, g, b);
185 | }
186 | else {
187 | // background, no energy
188 | leds[i] = CRGB(red_bg4, green_bg4, blue_bg4);
189 | }
190 | }
191 | }
192 | }
193 |
194 | void injectRandom4()
195 | {
196 | // random flame energy at bottom row
197 | for (int i=0; iaMax)
80 | aByte = aMax;
81 | else
82 | aByte = (byte)r;
83 | }
84 |
85 | uint16_t randomRainbow(uint16_t aMinOrMax, uint16_t aMax = 0)
86 | {
87 | if (aMax==0) {
88 | aMax = aMinOrMax;
89 | aMinOrMax = 0;
90 | }
91 | uint32_t r = aMinOrMax;
92 | aMax = aMax - aMinOrMax + 1;
93 | r += rand() % aMax;
94 | return r;
95 | }
96 |
97 | void resetEnergy8()
98 | {
99 | for (int i=0; i>8;
133 | // this cell becomes active spark
134 | energyMode8[i] = torch_spark8;
135 | }
136 | else {
137 | increase8(e, spark_tfr8);
138 | }
139 | break;
140 | }
141 | case torch_passive: {
142 | e = ((int)e*heat_cap8)>>8;
143 | increase8(e, ((((int)currentEnergy8[i-1]+(int)currentEnergy8[i+1])*side_rad8)>>9) + (((int)currentEnergy8[i-ledsPerLevel]*up_rad8)>>8));
144 | }
145 | default:
146 | break;
147 | }
148 | nextEnergy8[i++] = e;
149 | }
150 | }
151 | }
152 |
153 | const uint8_t energymap8[32] = {0, 64, 96, 112, 128, 144, 152, 160, 168, 176, 184, 184, 192, 200, 200, 208, 208, 216, 216, 224, 224, 224, 232, 232, 232, 240, 240, 240, 240, 248, 248, 248};
154 |
155 | void calcNextColors8()
156 | {
157 | for (int i=0; i250)
167 | leds[i] = ColorFromPalette( RainbowColors_p, 60); //CRGB(0, 15, e); // blueish extra-bright spark
168 | else {
169 | if (e>0) {
170 | // energy to brightness is non-linear
171 | byte eb = energymap[e>>3];
172 | byte r = red_bias8;
173 | byte g = green_bias8;
174 | byte b = blue_bias8;
175 | increase8(r, (eb*red_energy8)>>8);
176 | increase8(g, (eb*green_energy8)>>8);
177 | increase8(b, (eb*blue_energy8)>>8);
178 | leds[i] = CRGB(r, g, b);
179 | }
180 | else {
181 | // background, no energy
182 | leds[i] = CRGB(red_bg8, green_bg8, blue_bg8);
183 | }
184 | }
185 | }
186 | }
187 |
188 | void injectrandom8()
189 | {
190 | // random flame energy at bottom row
191 | for (int i=0; iaMax)
87 | aByte = aMax;
88 | else
89 | aByte = (byte)r;
90 | }
91 |
92 | uint16_t randomRed(uint16_t aMinOrMax, uint16_t aMax = 0)
93 | {
94 | if (aMax==0) {
95 | aMax = aMinOrMax;
96 | aMinOrMax = 0;
97 | }
98 | uint32_t r = aMinOrMax;
99 | aMax = aMax - aMinOrMax + 1;
100 | r += rand() % aMax;
101 | return r;
102 | }
103 |
104 | void resetEnergy()
105 | {
106 | for (int i=0; i>8;
140 | // this cell becomes active spark
141 | energyMode[i] = torch_spark;
142 | }
143 | else {
144 | increase(e, spark_tfr);
145 | }
146 | break;
147 | }
148 | case torch_passive: {
149 | e = ((int)e*heat_cap)>>8;
150 | increase(e, ((((int)currentEnergy[i-1]+(int)currentEnergy[i+1])*side_rad)>>9) + (((int)currentEnergy[i-ledsPerLevel]*up_rad)>>8));
151 | }
152 | default:
153 | break;
154 | }
155 | nextEnergy[i++] = e;
156 | }
157 | }
158 | }
159 |
160 | const uint8_t energymap[32] = {0, 64, 96, 112, 128, 144, 152, 160, 168, 176, 184, 184, 192, 200, 200, 208, 208, 216, 216, 224, 224, 224, 232, 232, 232, 240, 240, 240, 240, 248, 248, 248};
161 |
162 | void calcNextColors()
163 | {
164 | for (int i=0; i250)
173 | leds[i] = CRGB(170, 170, e); // blueish extra-bright spark
174 | else {
175 | if (e>0) {
176 | // energy to brightness is non-linear
177 | byte eb = energymap[e>>3];
178 | byte r = red_bias;
179 | byte g = green_bias;
180 | byte b = blue_bias;
181 | increase(r, (eb*red_energy)>>8);
182 | increase(g, (eb*green_energy)>>8);
183 | increase(b, (eb*blue_energy)>>8);
184 | leds[i] = CRGB(r, g, b);
185 | }
186 | else {
187 | // background, no energy
188 | leds[i] = CRGB(red_bg, green_bg, blue_bg);
189 | }
190 | }
191 | }
192 | }
193 |
194 | void injectRandom()
195 | {
196 | // random flame energy at bottom row
197 | for (int i=0; iaMax)
85 | aByte = aMax;
86 | else
87 | aByte = (byte)r;
88 | }
89 |
90 | uint16_t randomFireWhite(uint16_t aMinOrMax, uint16_t aMax = 0)
91 | {
92 | if (aMax==0) {
93 | aMax = aMinOrMax;
94 | aMinOrMax = 0;
95 | }
96 | uint32_t r = aMinOrMax;
97 | aMax = aMax - aMinOrMax + 1;
98 | r += rand() % aMax;
99 | return r;
100 | }
101 |
102 | void resetEnergyFireWhite()
103 | {
104 | for (int i=0; i>8;
138 | // this cell becomes active spark
139 | energyModeFireWhite[i] = torch_sparkFireWhite;
140 | }
141 | else {
142 | increaseFireWhite(e, spark_tfrFireWhite);
143 | }
144 | break;
145 | }
146 | case torch_passiveFireWhite: {
147 | e = ((int)e*heat_capFireWhite)>>8;
148 | increaseFireWhite(e, ((((int)currentEnergyFireWhite[i-1]+(int)currentEnergyFireWhite[i+1])*side_radFireWhite)>>9) + (((int)currentEnergyFireWhite[i-ledsPerLevel]*up_radFireWhite)>>8));
149 | }
150 | default:
151 | break;
152 | }
153 | nextEnergyFireWhite[i++] = e;
154 | }
155 | }
156 | }
157 |
158 | const uint8_t energymapFireWhite[32] = {0, 64, 96, 112, 128, 144, 152, 160, 168, 176, 184, 184, 192, 200, 200, 208, 208, 216, 216, 224, 224, 224, 232, 232, 232, 240, 240, 240, 240, 248, 248, 248};
159 |
160 | void calcNextColorsFireWhite()
161 | {
162 | for (int i=0; i250)
171 | leds[i] = CRGB(0, 0, 0); // blueish extra-bright spark
172 | else {
173 | if (e>0) {
174 | // energy to brightness is non-linear
175 | byte eb = energymapFireWhite[e>>3];
176 | byte r = red_biasFireWhite;
177 | byte g = green_biasFireWhite;
178 | byte b = blue_biasFireWhite;
179 | increaseFireWhite(r, (eb*red_energyFireWhite)>>8);
180 | increaseFireWhite(g, (eb*green_energyFireWhite)>>8);
181 | increaseFireWhite(b, (eb*blue_energyFireWhite)>>8);
182 | leds[i] = CRGB(r, g, b);
183 | }
184 | else {
185 | // background, no energy
186 | leds[i] = CRGB(red_bgFireWhite, green_bgFireWhite, blue_bgFireWhite);
187 | }
188 | }
189 | }
190 | }
191 |
192 | void injectRandomFireWhite()
193 | {
194 | // random flame energy at bottom row
195 | for (int i=0; i.
16 | *
17 | * ---------------------------------------------------------------------------------------------------*
18 | *
19 | * Modified by Making Things With LEDs https://www.youtube.com/@MakingThingsWithLEDs
20 | * I have left all previous comments from the original code writers in place, i ask you do the same.
21 | * If you use this code for your own projects and upload it please link back to the original sources.
22 | *
23 | * SUPPORT
24 | * Discord: https://discord.gg/SESbv89gq2
25 | */
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #if FASTLED_VERSION < 3001000
33 | #error "Requires FastLED 3.1 or later; check github for latest code."
34 | #endif
35 |
36 | #define LED_PIN 11 // Edit this to your required pin number (leave at 11 recommended)
37 | #define IR_RECV_PIN 12 // Pin for use with an IR remote control
38 | #define COLOR_ORDER GRB // LED order Green, Red, Blue as default
39 | #define CHIPSET 1, WS2812B // LED Chipset if using teensy 4.0 or above add 1, if below remove 1,
40 | #define NUM_LEDS 174 // How many leds total?
41 | #define MAX_POWER_MILLIAMPS 5000 // Power Supply In m/A 1000=1amp 5000=5amp 10000=10amp etc.
42 | #define BUTTON_1_PIN 16
43 | #define BUTTON_2_PIN 17
44 |
45 | const uint8_t MATRIX_WIDTH = 6; // Edit this to your matrix width
46 | const uint8_t MATRIX_HEIGHT = 29; // Edit this to your matrix height
47 |
48 | uint16_t XY(uint8_t x, uint8_t y);
49 | void dimAll(byte value);
50 | uint16_t ColorWaves();
51 | uint16_t Pride();
52 | uint16_t CloudTwinkles();
53 | uint16_t RainbowTwinkles();
54 | uint16_t SnowTwinkles();
55 | uint16_t IncandescentTwinkles();
56 | uint16_t Fireflies();
57 | uint16_t Rainbow();
58 | uint16_t RainbowWithGlitter();
59 | void AddGlitter(fract8 chanceOfGlitter);
60 | uint16_t Confetti();
61 | uint16_t BPM();
62 | uint16_t Juggle();
63 | uint16_t ShowSolidColor();
64 | uint16_t HueCycle();
65 | uint16_t Sinelon();
66 |
67 | const int MATRIX_CENTER_X = MATRIX_WIDTH / 2;
68 | const int MATRIX_CENTER_Y = MATRIX_HEIGHT / 2;
69 |
70 | const byte MATRIX_CENTRE_X = MATRIX_CENTER_X - 1;
71 | const byte MATRIX_CENTRE_Y = MATRIX_CENTER_Y - 1;
72 |
73 | const uint8_t brightnessCount = 5;
74 | uint8_t brightnessMap[brightnessCount] = { 16, 32, 64, 128, 255 };
75 | uint8_t brightness = brightnessMap[0];
76 |
77 | CRGB leds[NUM_LEDS + 1];
78 | IRrecv irReceiver(IR_RECV_PIN);
79 |
80 | Bounce button1 = Bounce();
81 | Bounce button2 = Bounce();
82 |
83 | #include "Commands.h"
84 | #include "GradientPalettes.h"
85 |
86 | CRGB solidColor = CRGB::Purple; //Solid Colour Effect
87 |
88 | typedef uint16_t(*PatternFunctionPointer)();
89 | typedef PatternFunctionPointer PatternList [];
90 | #define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
91 |
92 | int autoPlayDurationSeconds = 60; // Set automatic play time per effect adjust as required
93 | unsigned int autoPlayTimeout = 10;
94 | bool autoplayEnabled = true; // Disable / Enable automatic play function, use false if you wish to use momentary switch to control effects.
95 |
96 | InputCommand command;
97 |
98 | int currentPatternIndex = 0;
99 | PatternFunctionPointer currentPattern;
100 |
101 | CRGB w(85, 85, 85), W(CRGB::White);
102 | CRGBPalette16 snowColors = CRGBPalette16( W, W, W, W, w, w, w, w, w, w, w, w, w, w, w, w );
103 |
104 | CRGB l(0xE1A024);
105 | CRGBPalette16 incandescentColors = CRGBPalette16( l, l, l, l, l, l, l, l, l, l, l, l, l, l, l, l );
106 |
107 | const CRGBPalette16 palettes[] = {
108 | RainbowColors_p,
109 | RainbowStripeColors_p,
110 | OceanColors_p,
111 | CloudColors_p,
112 | ForestColors_p,
113 | PartyColors_p,
114 | HeatColors_p,
115 | LavaColors_p,
116 | snowColors,
117 | };
118 |
119 | const int paletteCount = ARRAY_SIZE(palettes);
120 |
121 | int currentPaletteIndex = 0;
122 | CRGBPalette16 palette = palettes[0];
123 |
124 | uint8_t gHue = 0; // rotating "base color" used by many of the patterns
125 |
126 | #include "Drawing.h"
127 | #include "Effects.h"
128 | #include "Noise.h"
129 | #include "Pulse.h"
130 | #include "Wave.h"
131 | #include "Fire2012WithPalette.h"
132 | #include "Fire2012Rainbow.h"
133 | #include "FireWhite.h"
134 | #include "FireRed.h"
135 | #include "FireGreen.h"
136 | #include "FireBlue.h"
137 | #include "FireElectricBlue.h"
138 | #include "FireChemical.h"
139 | #include "FireRainbow.h"
140 | #include "FirePurple.h"
141 | #include "FireOrange.h"
142 | #include "AudioLogic.h"
143 | #include "AudioPatterns.h"
144 | //===================================================================================================================================================START EFFECT PLAYLIST
145 | // EFFECTS LISTS // In automatic mode will display in order of the list.
146 | const PatternList patterns = { // remove or add // to enable/disable effects
147 |
148 | Analogous1,
149 | Aurora,
150 | BlackAndWhite,
151 | Calbayo15,
152 | Cloud,
153 | ColorCube,
154 | ColorWaves,
155 | CoralReef,
156 | Curvature,
157 | DeepSea,
158 | Fire2012Rainbow1,
159 | FireElectricBlue,
160 | FireBlue,
161 | FireChemical,
162 | FireGreen,
163 | FireOrange,
164 | FirePurple,
165 | FireRed,
166 | FireWhite,
167 | Forest,
168 | Lava,
169 | LavaLampRainbow,
170 | LavaLampRainbowStripe,
171 | Ocean,
172 | OceanBreeze,
173 | Party,
174 | RampRGB,
175 | Rstcurv,
176 | Shikon22,
177 | Shikon23,
178 | Spectrum,
179 | Temperature,
180 | Vintage49,
181 |
182 | //--Sound-Reactive-Effects--
183 | // AudioAnalyzerColumns,
184 | // AudioAnalyzerColumnsSolid,
185 | // AudioAnalyzerPixels,
186 | // AudioBlackAndBlue,
187 | // AudioBlackAndWhite,
188 | // AudioCloud,
189 | // AudioFallingSpectrogram,
190 | // AudioFire1,
191 | // AudioFire2,
192 | // AudioFire3,
193 | // AudioForest,
194 | // AudioLava,
195 | // AudioLava2,
196 | // AudioLavaMagenta,
197 | // AudioLavaRainbow,
198 | // AudioOcean,
199 | // AudioParty,
200 | // AudioRainbowStripe,
201 |
202 | //---Additional-Effects---
203 | // BPM,
204 | // CloudTwinkles,
205 | // Confetti,
206 | // Fire2012WithPalette,
207 | // Fireflies,
208 | // FireNoise,
209 | // HueCycle,
210 | // IncandescentTwinkles,
211 | // Juggle,
212 | // Pride,
213 | // Pulse,
214 | // Rainbow,
215 | // RainbowTwinkles,
216 | // RainbowWithGlitter,
217 | // ShowSolidColor,
218 | // Sinelon,
219 | // SnowTwinkles,
220 | // Wave,
221 |
222 | };
223 | //===================================================================================================================================================END EFFECT PLAYLIST
224 | const int patternCount = ARRAY_SIZE(patterns);
225 |
226 | void setup() {
227 | delay(1000); // sanity delay
228 | // Serial.begin(9600);
229 | // Serial.println("setup start");
230 |
231 | loadSettings();
232 |
233 | FastLED.addLeds(leds, NUM_LEDS);
234 | FastLED.setCorrection(TypicalLEDStrip);
235 | FastLED.setMaxPowerInVoltsAndMilliamps(5, MAX_POWER_MILLIAMPS); // Voltage, MAX_POWER_MILLIAMPS
236 | // FastLED.setBrightness(brightness);
237 | // FastLED.setDither(brightness < 255);
238 |
239 | // Initialize the IR receiver
240 | irReceiver.enableIRIn();
241 | irReceiver.blink13(true);
242 |
243 | pinMode(BUTTON_1_PIN, INPUT_PULLUP);
244 | pinMode(BUTTON_2_PIN, INPUT_PULLUP);
245 | button1.attach(BUTTON_1_PIN);
246 | button2.attach(BUTTON_2_PIN);
247 | button1.interval(5);
248 | button2.interval(5);
249 |
250 | currentPattern = patterns[currentPatternIndex];
251 | autoPlayTimeout = millis() + (autoPlayDurationSeconds * 1000);
252 |
253 | initializeAudio();
254 |
255 | // Serial.println("setup end");
256 | }
257 |
258 | void loop() {
259 | // Add entropy to random number generator; we use a lot of it.
260 | random16_add_entropy(random());
261 |
262 | EVERY_N_MILLISECONDS(30) {
263 | readAudio();
264 | }
265 |
266 | uint16_t requestedDelay = currentPattern();
267 |
268 | FastLED.show(); // display this frame
269 |
270 | handleInput(requestedDelay);
271 |
272 | if (autoplayEnabled && millis() > autoPlayTimeout) {
273 | move(1);
274 | autoPlayTimeout = millis() + (autoPlayDurationSeconds * 1000);
275 | }
276 |
277 | // do some periodic updates
278 | EVERY_N_MILLISECONDS(20) {
279 | gHue++; // slowly cycle the "base color" through the rainbow
280 | }
281 | }
282 |
283 | void loadSettings() {
284 | // load settings from EEPROM
285 |
286 | // brightness
287 | brightness = EEPROM.read(0);
288 | if (brightness < 1)
289 | brightness = 1;
290 | else if (brightness > 255)
291 | brightness = 255;
292 |
293 | // currentPatternIndex
294 | currentPatternIndex = EEPROM.read(1);
295 | if (currentPatternIndex < 0)
296 | currentPatternIndex = 0;
297 | else if (currentPatternIndex >= patternCount)
298 | currentPatternIndex = patternCount - 1;
299 |
300 | // solidColor
301 | solidColor.r = EEPROM.read(2);
302 | solidColor.g = EEPROM.read(3);
303 | solidColor.b = EEPROM.read(4);
304 |
305 | if (solidColor.r == 0 && solidColor.g == 0 && solidColor.b == 0)
306 | solidColor = CRGB::White;
307 | }
308 |
309 | void setSolidColor(CRGB color) {
310 | solidColor = color;
311 |
312 | EEPROM.write(2, solidColor.r);
313 | EEPROM.write(3, solidColor.g);
314 | EEPROM.write(4, solidColor.b);
315 |
316 | moveTo(patternCount - 1);
317 | }
318 |
319 | void powerOff()
320 | {
321 | // clear the display
322 | const uint8_t stepSize = 4;
323 |
324 | for (uint8_t i = 0; i < NUM_LEDS / 2 - stepSize; i += stepSize) {
325 | for (uint8_t j = 0; j < stepSize; j++) {
326 | leds[i + j] = CRGB::Black;
327 | leds[(NUM_LEDS - 1) - (i + j)] = CRGB::Black;
328 | }
329 | FastLED.show(); // display this frame
330 | }
331 |
332 | fill_solid(leds, NUM_LEDS, CRGB::Black);
333 |
334 | FastLED.show(); // display this frame
335 |
336 | while (true) {
337 | // check for physical button input
338 | button1.update();
339 | button2.update();
340 |
341 | if (button1.rose() || button2.rose()) {
342 | Serial.println("Button released");
343 | return;
344 | }
345 |
346 | // check for ir remote input
347 | InputCommand command = readCommand();
348 | if (command != InputCommand::None)
349 | return;
350 | }
351 | }
352 |
353 | void move(int delta) {
354 | moveTo(currentPatternIndex + delta);
355 | }
356 |
357 | void moveTo(int index) {
358 | currentPatternIndex = index;
359 |
360 | if (currentPatternIndex >= patternCount)
361 | currentPatternIndex = 0;
362 | else if (currentPatternIndex < 0)
363 | currentPatternIndex = patternCount - 1;
364 |
365 | currentPattern = patterns[currentPatternIndex];
366 |
367 | fill_solid(leds, NUM_LEDS, CRGB::Black);
368 |
369 | EEPROM.write(1, currentPatternIndex);
370 | }
371 |
372 | int getBrightnessLevel() {
373 | int level = 0;
374 | for (int i = 0; i < brightnessCount; i++) {
375 | if (brightnessMap[i] >= brightness) {
376 | level = i;
377 | break;
378 | }
379 | }
380 | return level;
381 | }
382 |
383 | uint8_t cycleBrightness() {
384 | adjustBrightness(1);
385 |
386 | if (brightness == brightnessMap[0])
387 | return 0;
388 |
389 | return brightness;
390 | }
391 |
392 | void adjustBrightness(int delta) {
393 | int level = getBrightnessLevel();
394 |
395 | level += delta;
396 |
397 | // don't wrap
398 | if (level < 0)
399 | level = 0;
400 | if (level >= brightnessCount)
401 | level = brightnessCount - 1;
402 |
403 | brightness = brightnessMap[level];
404 | FastLED.setBrightness(brightness);
405 | FastLED.setDither(brightness < 255);
406 |
407 | EEPROM.write(0, brightness);
408 | }
409 |
410 | void cyclePalette(int delta = 1) {
411 | if (currentPaletteIndex == 0 && delta < 0)
412 | currentPaletteIndex = paletteCount - 1;
413 | else if (currentPaletteIndex >= paletteCount - 1 && delta > 0)
414 | currentPaletteIndex = 0;
415 | else
416 | currentPaletteIndex += delta;
417 |
418 | if (currentPaletteIndex >= paletteCount)
419 | currentPaletteIndex = 0;
420 |
421 | palette = palettes[currentPaletteIndex];
422 | }
423 |
424 | unsigned long button1PressTimeStamp;
425 | unsigned long button2PressTimeStamp;
426 |
427 | void handleInput(unsigned int requestedDelay) {
428 | unsigned int requestedDelayTimeout = millis() + requestedDelay;
429 |
430 | while (true) {
431 | // check for physical button input
432 | button1.update();
433 | button2.update();
434 |
435 | if (button1.fell()) {
436 | Serial.println("Button 1 depressed");
437 | button1PressTimeStamp = millis();
438 | }
439 |
440 | if (button2.fell()) {
441 | Serial.println("Button 2 depressed");
442 | button2PressTimeStamp = millis();
443 | }
444 |
445 | if (button1.rose()) {
446 | Serial.println("Button 1 released");
447 | move(1);
448 | }
449 |
450 | if (button2.rose()) {
451 | Serial.println("Button 2 released");
452 | powerOff();
453 | break;
454 | }
455 |
456 | command = readCommand(defaultHoldDelay);
457 |
458 | if (command != InputCommand::None) {
459 | // Serial.print("command: ");
460 | // Serial.println((int) command);
461 | }
462 |
463 | if (command == InputCommand::Up) {
464 | move(1);
465 | break;
466 | }
467 | else if (command == InputCommand::Down) {
468 | move(-1);
469 | break;
470 | }
471 | else if (command == InputCommand::Brightness) {
472 | if (isHolding || cycleBrightness() == 0) {
473 | heldButtonHasBeenHandled();
474 | powerOff();
475 | break;
476 | }
477 | }
478 | else if (command == InputCommand::Power) {
479 | powerOff();
480 | break;
481 | }
482 | else if (command == InputCommand::BrightnessUp) {
483 | adjustBrightness(1);
484 | }
485 | else if (command == InputCommand::BrightnessDown) {
486 | adjustBrightness(-1);
487 | }
488 | else if (command == InputCommand::PlayMode) { // toggle pause/play
489 | autoplayEnabled = !autoplayEnabled;
490 | }
491 | else if (command == InputCommand::NextPalette) { // cycle color palette
492 | cyclePalette(1);
493 | }
494 | else if (command == InputCommand::PreviousPalette) { // cycle color palette
495 | cyclePalette(-1);
496 | }
497 |
498 | // pattern buttons
499 |
500 | else if (command == InputCommand::Pattern1) {
501 | moveTo(0);
502 | break;
503 | }
504 | else if (command == InputCommand::Pattern2) {
505 | moveTo(1);
506 | break;
507 | }
508 | else if (command == InputCommand::Pattern3) {
509 | moveTo(2);
510 | break;
511 | }
512 | else if (command == InputCommand::Pattern4) {
513 | moveTo(3);
514 | break;
515 | }
516 | else if (command == InputCommand::Pattern5) {
517 | moveTo(4);
518 | break;
519 | }
520 | else if (command == InputCommand::Pattern6) {
521 | moveTo(5);
522 | break;
523 | }
524 | else if (command == InputCommand::Pattern7) {
525 | moveTo(6);
526 | break;
527 | }
528 | else if (command == InputCommand::Pattern8) {
529 | moveTo(7);
530 | break;
531 | }
532 | else if (command == InputCommand::Pattern9) {
533 | moveTo(8);
534 | break;
535 | }
536 | else if (command == InputCommand::Pattern10) {
537 | moveTo(9);
538 | break;
539 | }
540 | else if (command == InputCommand::Pattern11) {
541 | moveTo(10);
542 | break;
543 | }
544 | else if (command == InputCommand::Pattern12) {
545 | moveTo(11);
546 | break;
547 | }
548 |
549 | // custom color adjustment buttons
550 |
551 | else if (command == InputCommand::RedUp) {
552 | solidColor.red += 1;
553 | setSolidColor(solidColor);
554 | break;
555 | }
556 | else if (command == InputCommand::RedDown) {
557 | solidColor.red -= 1;
558 | setSolidColor(solidColor);
559 | break;
560 | }
561 | else if (command == InputCommand::GreenUp) {
562 | solidColor.green += 1;
563 | setSolidColor(solidColor); \
564 | break;
565 | }
566 | else if (command == InputCommand::GreenDown) {
567 | solidColor.green -= 1;
568 | setSolidColor(solidColor);
569 | break;
570 | }
571 | else if (command == InputCommand::BlueUp) {
572 | solidColor.blue += 1;
573 | setSolidColor(solidColor);
574 | break;
575 | }
576 | else if (command == InputCommand::BlueDown) {
577 | solidColor.blue -= 1;
578 | setSolidColor(solidColor);
579 | break;
580 | }
581 |
582 | // color buttons
583 |
584 | else if (command == InputCommand::Red && currentPatternIndex != patternCount - 2 && currentPatternIndex != patternCount - 3) { // Red, Green, and Blue buttons can be used by ColorInvaders game, which is the next to last pattern
585 | setSolidColor(CRGB::Red);
586 | break;
587 | }
588 | else if (command == InputCommand::RedOrange) {
589 | setSolidColor(CRGB::OrangeRed);
590 | break;
591 | }
592 | else if (command == InputCommand::Orange) {
593 | setSolidColor(CRGB::Orange);
594 | break;
595 | }
596 | else if (command == InputCommand::YellowOrange) {
597 | setSolidColor(CRGB::Goldenrod);
598 | break;
599 | }
600 | else if (command == InputCommand::Yellow) {
601 | setSolidColor(CRGB::Yellow);
602 | break;
603 | }
604 |
605 | else if (command == InputCommand::Green && currentPatternIndex != patternCount - 2 && currentPatternIndex != patternCount - 3) { // Red, Green, and Blue buttons can be used by ColorInvaders game, which is the next to last pattern
606 | setSolidColor(CRGB::Green);
607 | break;
608 | }
609 | else if (command == InputCommand::Lime) {
610 | setSolidColor(CRGB::Lime);
611 | break;
612 | }
613 | else if (command == InputCommand::Aqua) {
614 | setSolidColor(CRGB::Aqua);
615 | break;
616 | }
617 | else if (command == InputCommand::Teal) {
618 | setSolidColor(CRGB::Teal);
619 | break;
620 | }
621 | else if (command == InputCommand::Navy) {
622 | setSolidColor(CRGB::Navy);
623 | break;
624 | }
625 |
626 | else if (command == InputCommand::Blue && currentPatternIndex != patternCount - 2 && currentPatternIndex != patternCount - 3) { // Red, Green, and Blue buttons can be used by ColorInvaders game, which is the next to last pattern
627 | setSolidColor(CRGB::Blue);
628 | break;
629 | }
630 | else if (command == InputCommand::RoyalBlue) {
631 | setSolidColor(CRGB::RoyalBlue);
632 | break;
633 | }
634 | else if (command == InputCommand::Purple) {
635 | setSolidColor(CRGB::Purple);
636 | break;
637 | }
638 | else if (command == InputCommand::Indigo) {
639 | setSolidColor(CRGB::Indigo);
640 | break;
641 | }
642 | else if (command == InputCommand::Magenta) {
643 | setSolidColor(CRGB::Magenta);
644 | break;
645 | }
646 |
647 | else if (command == InputCommand::White && currentPatternIndex != patternCount - 2 && currentPatternIndex != patternCount - 3) {
648 | setSolidColor(CRGB::White);
649 | break;
650 | }
651 | else if (command == InputCommand::Pink) {
652 | setSolidColor(CRGB::Pink);
653 | break;
654 | }
655 | else if (command == InputCommand::LightPink) {
656 | setSolidColor(CRGB::LightPink);
657 | break;
658 | }
659 | else if (command == InputCommand::BabyBlue) {
660 | setSolidColor(CRGB::CornflowerBlue);
661 | break;
662 | }
663 | else if (command == InputCommand::LightBlue) {
664 | setSolidColor(CRGB::LightBlue);
665 | break;
666 | }
667 |
668 | if (millis() >= requestedDelayTimeout)
669 | break;
670 | }
671 | }
672 |
673 | uint16_t XY( uint8_t x, uint8_t y) // maps the matrix to the strip
674 | {
675 | uint16_t i;
676 | i = (y * MATRIX_WIDTH) + (MATRIX_WIDTH - x);
677 |
678 | i = (NUM_LEDS - 1) - i;
679 |
680 | if (i > NUM_LEDS)
681 | i = NUM_LEDS;
682 |
683 | return i;
684 | }
685 |
686 | // scale the brightness of the screenbuffer down
687 | void dimAll(byte value)
688 | {
689 | for (int i = 0; i < NUM_LEDS; i++) {
690 | leds[i].nscale8(value);
691 | }
692 | }
693 | //===============================================
694 | uint16_t ShowSolidColor() {
695 | fill_solid(leds, NUM_LEDS, solidColor);
696 |
697 | return 60;
698 | }
699 | //===============================================
700 | uint16_t Rainbow()
701 | {
702 | // FastLED's built-in rainbow generator
703 | fill_rainbow(leds, NUM_LEDS, gHue, 1);
704 |
705 | return 8;
706 | }
707 | //===============================================
708 | uint16_t RainbowWithGlitter()
709 | {
710 | // built-in FastLED rainbow, plus some random sparkly glitter
711 | Rainbow();
712 | AddGlitter(80);
713 | return 8;
714 | }
715 | //===============================================
716 | void AddGlitter(fract8 chanceOfGlitter)
717 | {
718 | if (random8() < chanceOfGlitter) {
719 | leds[random16(NUM_LEDS)] += CRGB::White;
720 | }
721 | }
722 | //===============================================
723 | uint16_t Confetti()
724 | {
725 | // random colored speckles that blink in and fade smoothly
726 | fadeToBlackBy(leds, NUM_LEDS, 10);
727 | int pos = random16(NUM_LEDS);
728 | leds[pos] += ColorFromPalette(palette, gHue + random8(64), 255); // CHSV(gHue + random8(64), 200, 255);
729 | return 8;
730 | }
731 | //===============================================
732 | uint16_t BPM()
733 | {
734 | // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
735 | uint8_t BeatsPerMinute = 62;
736 | uint8_t beat = beatsin8(BeatsPerMinute, 64, 255);
737 | for (int i = 0; i < NUM_LEDS; i++) { //9948
738 | leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10));
739 | }
740 | return 8;
741 | }
742 | //===============================================
743 | uint16_t Juggle() {
744 | // N colored dots, weaving in and out of sync with each other
745 | fadeToBlackBy(leds, NUM_LEDS, 20);
746 | byte dothue = 1;
747 | byte dotCount = 3;
748 | for (int i = 0; i < dotCount; i++) {
749 | leds[beatsin16(i + dotCount - 1, 0, NUM_LEDS)] |= CHSV(dothue, 200, 255);
750 | dothue += 256 / dotCount;
751 | }
752 | return 0;
753 | }
754 | //===============================================
755 | // An animation to play while the crowd goes wild after the big performance
756 | uint16_t Applause()
757 | {
758 | static uint16_t lastPixel = 0;
759 | fadeToBlackBy(leds, NUM_LEDS, 32);
760 | leds[lastPixel] = CHSV(random8(HUE_BLUE, HUE_PURPLE), 255, 255);
761 | lastPixel = random16(NUM_LEDS);
762 | leds[lastPixel] = CRGB::White;
763 | return 8;
764 | }
765 | //===============================================
766 | // An "animation" to just fade to black. Useful as the last track
767 | // in a non-looping performance-oriented playlist.
768 | uint16_t fadeToBlack()
769 | {
770 | fadeToBlackBy(leds, NUM_LEDS, 10);
771 | return 8;
772 | }
773 | //===============================================
774 | uint16_t Sinelon()
775 | {
776 | // a colored dot sweeping back and forth, with fading trails
777 | fadeToBlackBy( leds, NUM_LEDS, 20);
778 | uint16_t pos = beatsin16(13, 0, NUM_LEDS);
779 | static uint16_t prevpos = 0;
780 | if ( pos < prevpos ) {
781 | fill_solid( leds + pos, (prevpos - pos) + 1, CHSV(gHue, 220, 255));
782 | } else {
783 | fill_solid( leds + prevpos, (pos - prevpos) + 1, CHSV( gHue, 220, 255));
784 | }
785 | prevpos = pos;
786 |
787 | return 8;
788 | }
789 | //===============================================
790 | uint16_t HueCycle() {
791 | fill_solid(leds, NUM_LEDS, CHSV(gHue, 255, 255));
792 | return 60;
793 | }
794 | //===============================================
795 | // Pride2015 by Mark Kriegsman
796 | // https://gist.github.com/kriegsman/964de772d64c502760e5
797 |
798 | // This function draws rainbows with an ever-changing,
799 | // widely-varying set of parameters.
800 | uint16_t Pride()
801 | {
802 | static uint16_t sPseudotime = 0;
803 | static uint16_t sLastMillis = 0;
804 | static uint16_t sHue16 = 0;
805 |
806 | uint8_t sat8 = beatsin88(87, 220, 250);
807 | uint8_t brightdepth = beatsin88(341, 96, 224);
808 | uint16_t brightnessthetainc16 = beatsin88(203, (25 * 256), (40 * 256));
809 | uint8_t msmultiplier = beatsin88(147, 23, 60);
810 |
811 | uint16_t hue16 = sHue16;//gHue * 256;
812 | uint16_t hueinc16 = beatsin88(113, 1, 3000);
813 |
814 | uint16_t ms = millis();
815 | uint16_t deltams = ms - sLastMillis;
816 | sLastMillis = ms;
817 | sPseudotime += deltams * msmultiplier;
818 | sHue16 += deltams * beatsin88(400, 5, 9);
819 | uint16_t brightnesstheta16 = sPseudotime;
820 |
821 | for (int i = 0; i < NUM_LEDS; i++) {
822 | hue16 += hueinc16;
823 | uint8_t hue8 = hue16 / 256;
824 |
825 | brightnesstheta16 += brightnessthetainc16;
826 | uint16_t b16 = sin16(brightnesstheta16) + 32768;
827 |
828 | uint16_t bri16 = (uint32_t) ((uint32_t) b16 * (uint32_t) b16) / 65536;
829 | uint8_t bri8 = (uint32_t) (((uint32_t) bri16) * brightdepth) / 65536;
830 | bri8 += (255 - brightdepth);
831 |
832 | CRGB newcolor = CHSV(hue8, sat8, bri8);
833 |
834 | uint8_t pixelnumber = i;
835 | pixelnumber = (NUM_LEDS - 1) - pixelnumber;
836 |
837 | nblend(leds[pixelnumber], newcolor, 64);
838 | }
839 |
840 | return 0;
841 | }
842 |
843 | ///////////////////////////////////////////////////////////////////////
844 |
845 | // Forward declarations of an array of cpt-city gradient palettes, and
846 | // a count of how many there are. The actual color palette definitions
847 | // are at the bottom of this file.
848 | extern const TProgmemRGBGradientPalettePtr gGradientPalettes[];
849 | extern const uint8_t gGradientPaletteCount;
850 |
851 | // Current palette number from the 'playlist' of color palettes
852 | uint8_t gCurrentPaletteNumber = 0;
853 |
854 | CRGBPalette16 gCurrentPalette( CRGB::Black);
855 | CRGBPalette16 gTargetPalette( gGradientPalettes[0] );
856 |
857 | // ten seconds per color palette makes a good demo
858 | // 20-120 is better for deployment
859 | #define SECONDS_PER_PALETTE 10
860 |
861 | uint16_t ColorWaves()
862 | {
863 | EVERY_N_SECONDS( SECONDS_PER_PALETTE ) {
864 | gCurrentPaletteNumber = addmod8( gCurrentPaletteNumber, 1, gGradientPaletteCount);
865 | gTargetPalette = gGradientPalettes[ gCurrentPaletteNumber ];
866 | }
867 |
868 | EVERY_N_MILLISECONDS(40) {
869 | nblendPaletteTowardPalette( gCurrentPalette, gTargetPalette, 16);
870 | }
871 |
872 | Colorwaves( leds, NUM_LEDS, gCurrentPalette);
873 |
874 | return 20;
875 | }
876 |
877 |
878 | // This function draws color waves with an ever-changing,
879 | // widely-varying set of parameters, using a color palette.
880 | void Colorwaves( CRGB* ledarray, uint16_t numleds, CRGBPalette16& palette)
881 | {
882 | static uint16_t sPseudotime = 0;
883 | static uint16_t sLastMillis = 0;
884 | static uint16_t sHue16 = 0;
885 |
886 | // uint8_t sat8 = beatsin88( 87, 220, 250);
887 | uint8_t brightdepth = beatsin88( 341, 96, 224);
888 | uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256));
889 | uint8_t msmultiplier = beatsin88(147, 23, 60);
890 |
891 | uint16_t hue16 = sHue16;//gHue * 256;
892 | uint16_t hueinc16 = beatsin88(113, 300, 1500);
893 |
894 | uint16_t ms = millis();
895 | uint16_t deltams = ms - sLastMillis ;
896 | sLastMillis = ms;
897 | sPseudotime += deltams * msmultiplier;
898 | sHue16 += deltams * beatsin88( 400, 5, 9);
899 | uint16_t brightnesstheta16 = sPseudotime;
900 |
901 | for ( uint16_t i = 0 ; i < numleds; i++) {
902 | hue16 += hueinc16;
903 | uint8_t hue8 = hue16 / 256;
904 | uint16_t h16_128 = hue16 >> 7;
905 | if ( h16_128 & 0x100) {
906 | hue8 = 255 - (h16_128 >> 1);
907 | } else {
908 | hue8 = h16_128 >> 1;
909 | }
910 |
911 | brightnesstheta16 += brightnessthetainc16;
912 | uint16_t b16 = sin16( brightnesstheta16 ) + 32768;
913 |
914 | uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536;
915 | uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536;
916 | bri8 += (255 - brightdepth);
917 |
918 | uint8_t index = hue8;
919 | //index = triwave8( index);
920 | index = scale8( index, 240);
921 |
922 | CRGB newcolor = ColorFromPalette( palette, index, bri8);
923 |
924 | uint16_t pixelnumber = i;
925 | pixelnumber = (numleds - 1) - pixelnumber;
926 |
927 | nblend( ledarray[pixelnumber], newcolor, 128);
928 | }
929 | }
930 |
931 | // Alternate rendering function just scrolls the current palette
932 | // across the defined LED strip.
933 | void palettetest( CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurrentPalette)
934 | {
935 | static uint8_t startindex = 0;
936 | startindex--;
937 | fill_palette( ledarray, numleds, startindex, (256 / NUM_LEDS) + 1, gCurrentPalette, 255, LINEARBLEND);
938 | }
939 |
940 | #define STARTING_BRIGHTNESS 64
941 | #define FADE_IN_SPEED 32
942 | #define FADE_OUT_SPEED 20
943 | uint8_t DENSITY = 255;
944 | //===============================================
945 | uint16_t CloudTwinkles()
946 | {
947 | DENSITY = 255;
948 | colortwinkles(CloudColors_p);
949 | return 20;
950 | }
951 | //===============================================
952 | uint16_t RainbowTwinkles()
953 | {
954 | DENSITY = 255;
955 | colortwinkles(RainbowColors_p);
956 | return 20;
957 | }
958 | //===============================================
959 | uint16_t SnowTwinkles()
960 | {
961 | DENSITY = 255;
962 | colortwinkles(snowColors);
963 | return 20;
964 | }
965 | //===============================================
966 | uint16_t IncandescentTwinkles()
967 | {
968 | DENSITY = 255;
969 | colortwinkles(incandescentColors);
970 | return 20;
971 | }
972 | //===============================================
973 | uint16_t Fireflies()
974 | {
975 | DENSITY = 16;
976 | colortwinkles(incandescentColors);
977 | return 20;
978 | }
979 | //===============================================
980 | enum { GETTING_DARKER = 0, GETTING_BRIGHTER = 1 };
981 |
982 | void colortwinkles(CRGBPalette16 palette)
983 | {
984 | // Make each pixel brighter or darker, depending on
985 | // its 'direction' flag.
986 | brightenOrDarkenEachPixel( FADE_IN_SPEED, FADE_OUT_SPEED);
987 |
988 | // Now consider adding a new random twinkle
989 | if ( random8() < DENSITY ) {
990 | int pos = random16(NUM_LEDS);
991 | if ( !leds[pos]) {
992 | leds[pos] = ColorFromPalette( palette, random8(), STARTING_BRIGHTNESS, NOBLEND);
993 | setPixelDirection(pos, GETTING_BRIGHTER);
994 | }
995 | }
996 | }
997 |
998 | void brightenOrDarkenEachPixel( fract8 fadeUpAmount, fract8 fadeDownAmount)
999 | {
1000 | for ( uint16_t i = 0; i < NUM_LEDS; i++) {
1001 | if ( getPixelDirection(i) == GETTING_DARKER) {
1002 | // This pixel is getting darker
1003 | leds[i] = makeDarker( leds[i], fadeDownAmount);
1004 | } else {
1005 | // This pixel is getting brighter
1006 | leds[i] = makeBrighter( leds[i], fadeUpAmount);
1007 | // now check to see if we've maxxed out the brightness
1008 | if ( leds[i].r == 255 || leds[i].g == 255 || leds[i].b == 255) {
1009 | // if so, turn around and start getting darker
1010 | setPixelDirection(i, GETTING_DARKER);
1011 | }
1012 | }
1013 | }
1014 | }
1015 |
1016 | CRGB makeBrighter( const CRGB& color, fract8 howMuchBrighter)
1017 | {
1018 | CRGB incrementalColor = color;
1019 | incrementalColor.nscale8( howMuchBrighter);
1020 | return color + incrementalColor;
1021 | }
1022 |
1023 | CRGB makeDarker( const CRGB& color, fract8 howMuchDarker)
1024 | {
1025 | CRGB newcolor = color;
1026 | newcolor.nscale8( 255 - howMuchDarker);
1027 | return newcolor;
1028 | }
1029 |
1030 | // Compact implementation of
1031 | // the directionFlags array, using just one BIT of RAM
1032 | // per pixel. This requires a bunch of bit wrangling,
1033 | // but conserves precious RAM. The cost is a few
1034 | // cycles and about 100 bytes of flash program memory.
1035 | uint8_t directionFlags[ (NUM_LEDS + 7) / 8];
1036 |
1037 | bool getPixelDirection( uint16_t i) {
1038 | uint16_t index = i / 8;
1039 | uint8_t bitNum = i & 0x07;
1040 |
1041 | uint8_t andMask = 1 << bitNum;
1042 | return (directionFlags[index] & andMask) != 0;
1043 | }
1044 |
1045 | void setPixelDirection( uint16_t i, bool dir) {
1046 | uint16_t index = i / 8;
1047 | uint8_t bitNum = i & 0x07;
1048 |
1049 | uint8_t orMask = 1 << bitNum;
1050 | uint8_t andMask = 255 - orMask;
1051 | uint8_t value = directionFlags[index] & andMask;
1052 | if ( dir ) {
1053 | value += orMask;
1054 | }
1055 | directionFlags[index] = value;
1056 | }
1057 |
--------------------------------------------------------------------------------
/Noise.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Torch: https://github.com/evilgeniuslabs/torch
3 | * Copyright (C) 2015 Jason Coon
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | #define MAX_DIMENSION ((MATRIX_WIDTH > MATRIX_HEIGHT) ? MATRIX_WIDTH : MATRIX_HEIGHT)
20 |
21 | // The 16 bit version of our coordinates
22 | static uint16_t noisex;
23 | static uint16_t noisey;
24 | static uint16_t noisez;
25 |
26 | // We're using the x/y dimensions to map to the x/y pixels on the matrix. We'll
27 | // use the z-axis for "time". speed determines how fast time moves forward. Try
28 | // 1 for a very slow moving effect, or 60 for something that ends up looking like
29 | // water.
30 | uint32_t noisespeedx = 1;
31 | uint32_t noisespeedy = 1;
32 | uint32_t noisespeedz = 1;
33 |
34 | // Scale determines how far apart the pixels in our noise matrix are. Try
35 | // changing these values around to see how it affects the motion of the display. The
36 | // higher the value of scale, the more "zoomed out" the noise will be. A value
37 | // of 1 will be so zoomed in, you'll mostly see solid colors.
38 | uint16_t noisescale = 30; // scale is set dynamically once we've started up
39 |
40 | // This is the array that we keep our computed noise values in
41 | uint8_t noise[MAX_DIMENSION][MAX_DIMENSION];
42 |
43 | uint8_t colorLoop = 0;
44 |
45 | CRGBPalette16 blackAndWhiteStripedPalette;
46 |
47 | // This function sets up a palette of black and white stripes,
48 | // using code. Since the palette is effectively an array of
49 | // sixteen CRGB colors, the various fill_* functions can be used
50 | // to set them up.
51 | void SetupBlackAndWhiteStripedPalette()
52 | {
53 | // 'black out' all 16 palette entries...
54 | fill_solid( blackAndWhiteStripedPalette, 16, CRGB::Black);
55 | // and set every fourth one to white.
56 | blackAndWhiteStripedPalette[0] = CRGB::White;
57 | blackAndWhiteStripedPalette[4] = CRGB::White;
58 | blackAndWhiteStripedPalette[8] = CRGB::White;
59 | blackAndWhiteStripedPalette[12] = CRGB::White;
60 |
61 | }
62 |
63 | CRGBPalette16 blackAndBlueStripedPalette;
64 |
65 | // This function sets up a palette of black and blue stripes,
66 | // using code. Since the palette is effectively an array of
67 | // sixteen CRGB colors, the various fill_* functions can be used
68 | // to set them up.
69 | void SetupBlackAndBlueStripedPalette()
70 | {
71 | // 'black out' all 16 palette entries...
72 | fill_solid( blackAndBlueStripedPalette, 16, CRGB::Black);
73 |
74 | for(uint8_t i = 0; i < 6; i++) {
75 | blackAndBlueStripedPalette[i] = CRGB::Blue;
76 | }
77 | }
78 |
79 | // There are several different palettes of colors demonstrated here.
80 | //
81 | // FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p,
82 | // OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p.
83 | //
84 | // Additionally, you can manually define your own color palettes, or you can write
85 | // code that creates color palettes on the fly.
86 |
87 | boolean initialized = false;
88 |
89 | // Fill the x/y array of 8-bit noise values using the inoise8 function.
90 | void fillnoise8() {
91 |
92 | if(!initialized) {
93 | initialized = true;
94 | // Initialize our coordinates to some random values
95 | noisex = random16();
96 | noisey = random16();
97 | noisez = random16();
98 | }
99 |
100 | // If we're runing at a low "speed", some 8-bit artifacts become visible
101 | // from frame-to-frame. In order to reduce this, we can do some fast data-smoothing.
102 | // The amount of data smoothing we're doing depends on "speed".
103 | uint8_t dataSmoothing = 0;
104 | uint16_t lowestNoise = noisespeedx < noisespeedy ? noisespeedx : noisespeedy;
105 | lowestNoise = lowestNoise < noisespeedz ? lowestNoise : noisespeedz;
106 | if( lowestNoise < 8) {
107 | dataSmoothing = 200 - (lowestNoise * 4);
108 | }
109 |
110 | for(int i = 0; i < MAX_DIMENSION; i++) {
111 | int ioffset = noisescale * i;
112 | for(int j = 0; j < MAX_DIMENSION; j++) {
113 | int joffset = noisescale * j;
114 |
115 | uint8_t data = inoise8(noisex + ioffset, noisey + joffset, noisez);
116 |
117 | // The range of the inoise8 function is roughly 16-238.
118 | // These two operations expand those values out to roughly 0..255
119 | // You can comment them out if you want the raw noise data.
120 | data = qsub8(data,16);
121 | data = qadd8(data,scale8(data,39));
122 |
123 | if( dataSmoothing ) {
124 | uint8_t olddata = noise[i][j];
125 | uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing);
126 | data = newdata;
127 | }
128 |
129 | noise[i][j] = data;
130 | }
131 | }
132 |
133 | noisex += noisespeedx;
134 | noisey += noisespeedy;
135 | noisez += noisespeedz;
136 | }
137 |
138 | void mapNoiseToLEDsUsingPalette(CRGBPalette16 palette, uint8_t hueReduce = 0)
139 | {
140 | static uint8_t ihue=0;
141 |
142 | for(int i = 0; i < MATRIX_WIDTH; i++) {
143 | for(int j = 0; j < MATRIX_HEIGHT; j++) {
144 | // We use the value at the (i,j) coordinate in the noise
145 | // array for our brightness, and the flipped value from (j,i)
146 | // for our pixel's index into the color palette.
147 |
148 | uint8_t index = noise[j][i];
149 | uint8_t bri = noise[i][j];
150 |
151 | // if this palette is a 'loop', add a slowly-changing base value
152 | if( colorLoop) {
153 | index += ihue;
154 | }
155 |
156 | // brighten up, as the color palette itself often contains the
157 | // light/dark dynamic range desired
158 | if( bri > 127 ) {
159 | bri = 255;
160 | } else {
161 | bri = dim8_raw( bri * 2);
162 | }
163 |
164 | if(hueReduce > 0) {
165 | if(index < hueReduce) index = 0;
166 | else index -= hueReduce;
167 | }
168 |
169 | CRGB color = ColorFromPalette( palette, index, bri);
170 | uint16_t n = XY(i, j);
171 |
172 | leds[n] = color;
173 | }
174 | }
175 |
176 | ihue+=1;
177 | }
178 |
179 | uint16_t drawNoise(CRGBPalette16 palette,uint8_t hueReduce = 0) {
180 | // generate noise data
181 | fillnoise8();
182 |
183 | // convert the noise data to colors in the LED array
184 | // using the current palette
185 | mapNoiseToLEDsUsingPalette(palette, hueReduce);
186 |
187 | return 10;
188 | }
189 | //===============================================
190 | uint16_t LavaLampRainbow() {
191 | noisespeedx = 1;
192 | noisespeedy = 0;
193 | noisespeedz = 0;
194 | noisescale = 10;
195 | colorLoop = 0;
196 | return drawNoise(RainbowColors_p);
197 | }
198 | //===============================================
199 | uint16_t LavaLampRainbowStripe() {
200 | noisespeedx = 2;
201 | noisespeedy = 0;
202 | noisespeedz = 0;
203 | noisescale = 20;
204 | colorLoop = 0;
205 | return drawNoise(RainbowStripeColors_p);
206 | }
207 | //===============================================
208 | uint16_t Party() {
209 | noisespeedx = 1;
210 | noisespeedy = 0;
211 | noisespeedz = 0;
212 | noisescale = 50;
213 | colorLoop = 0;
214 | return drawNoise(PartyColors_p);
215 | }
216 | //===============================================
217 | uint16_t Forest() {
218 | noisespeedx = 9;
219 | noisespeedy = 0;
220 | noisespeedz = 0;
221 | noisescale = 120;
222 | colorLoop = 0;
223 | return drawNoise(ForestColors_p);
224 | }
225 | //===============================================
226 | uint16_t Cloud() {
227 | noisespeedx = 9;
228 | noisespeedy = 0;
229 | noisespeedz = 0;
230 | noisescale = 30;
231 | colorLoop = 0;
232 | return drawNoise(CloudColors_p);
233 | }
234 | //===============================================
235 | uint16_t Fire() {
236 | noisespeedx = 8; // 24;
237 | noisespeedy = 0;
238 | noisespeedz = 8;
239 | noisescale = 50;
240 | colorLoop = 0;
241 | return drawNoise(HeatColors_p, 60);
242 | }
243 | //===============================================
244 | uint16_t FireNoise() {
245 | noisespeedx = 8; // 24;
246 | noisespeedy = 0;
247 | noisespeedz = 8;
248 | noisescale = 50;
249 | colorLoop = 0;
250 | return drawNoise(HeatColors_p, 60);
251 | }
252 | //===============================================
253 | uint16_t Lava() {
254 | noisespeedx = 2;
255 | noisespeedy = 0;
256 | noisespeedz = 2;
257 | noisescale = 20;
258 | colorLoop = 0;
259 | return drawNoise(LavaColors_p);
260 | }
261 | //===============================================
262 | uint16_t Ocean() {
263 | noisespeedx = 9;
264 | noisespeedy = 0;
265 | noisespeedz = 0;
266 | noisescale = 90;
267 | colorLoop = 0;
268 | return drawNoise(OceanColors_p);
269 | }
270 | //===============================================
271 | uint16_t BlackAndWhite() {
272 | SetupBlackAndWhiteStripedPalette();
273 | noisespeedx = 9;
274 | noisespeedy = 0;
275 | noisespeedz = 0;
276 | noisescale = 30;
277 | colorLoop = 0;
278 | return drawNoise(blackAndWhiteStripedPalette);
279 | }
280 | //===============================================
281 | uint16_t BlackAndBlue() {
282 | SetupBlackAndBlueStripedPalette();
283 | noisespeedx = 9;
284 | noisespeedy = 0;
285 | noisespeedz = 0;
286 | noisescale = 30;
287 | colorLoop = 0;
288 | return drawNoise(blackAndBlueStripedPalette);
289 | }
290 | //===============================================
291 | uint16_t Temperature() {
292 | noisespeedx = 1;
293 | noisespeedy = 0;
294 | noisespeedz = 1;
295 | noisescale = 25; //20
296 | colorLoop = 0;
297 | return drawNoise(temperature_gp);
298 | }
299 | //===============================================
300 | uint16_t Spectrum() {
301 | noisespeedx = 1;
302 | noisespeedy = 0;
303 | noisespeedz = 1;
304 | noisescale = 25; //20
305 | colorLoop = 0;
306 | return drawNoise(Stripped_Spectrum_gp);
307 | }
308 | //===============================================
309 | uint16_t OceanBreeze() {
310 | noisespeedx = 1;
311 | noisespeedy = 0;
312 | noisespeedz = 1;
313 | noisescale = 25; //20
314 | colorLoop = 0;
315 | return drawNoise(es_ocean_breeze_026_gp);
316 | }
317 | //===============================================
318 | uint16_t DeepSea() {
319 | noisespeedx = 1;
320 | noisespeedy = 1;
321 | noisespeedz = 0;
322 | noisescale = 30; //20
323 | colorLoop = 0;
324 | return drawNoise(Deep_Sea_gp);
325 | }
326 | //===============================================
327 | uint16_t Aurora() {
328 | noisespeedx = 0;
329 | noisespeedy = 1;
330 | noisespeedz = 0;
331 | noisescale = 30; //20
332 | colorLoop = 0;
333 | return drawNoise(ofaurora_gp);
334 | }
335 | //===============================================
336 | uint16_t Shikon22() {
337 | noisespeedx = 1;
338 | noisespeedy = 1;
339 | noisespeedz = 0;
340 | noisescale = 10; //20
341 | colorLoop = 0;
342 | return drawNoise(shikon_22_gp);
343 | }
344 | //===============================================
345 | uint16_t Shikon23() {
346 | noisespeedx = 1;
347 | noisespeedy = 1;
348 | noisespeedz = 0;
349 | noisescale = 10; //20
350 | colorLoop = 0;
351 | return drawNoise(shikon_23_gp);
352 | }
353 | //===============================================
354 | uint16_t ColorCube() {
355 | noisespeedx = 1;
356 | noisespeedy = 1;
357 | noisespeedz = 0;
358 | noisescale = 15; //20
359 | colorLoop = 0;
360 | return drawNoise(colorcube_gp);
361 | }
362 | //===============================================
363 | uint16_t RampRGB() {
364 | noisespeedx = 0;
365 | noisespeedy = 0;
366 | noisespeedz = 1;
367 | noisescale = 6; //20
368 | colorLoop = 0;
369 | return drawNoise(ramp_gp);
370 | }
371 | //===============================================
372 | uint16_t Curvature() {
373 | noisespeedx = 0;
374 | noisespeedy = 0;
375 | noisespeedz = 1;
376 | noisescale = 6; //20
377 | colorLoop = 0;
378 | return drawNoise(curvature_gp);
379 | }
380 | //===============================================
381 | uint16_t Rstcurv() {
382 | noisespeedx = 2;
383 | noisespeedy = 2;
384 | noisespeedz = 1;
385 | noisescale = 50; //20
386 | colorLoop = 0;
387 | return drawNoise(rstcurv_gp);
388 | }
389 | //===============================================
390 | uint16_t Calbayo15() {
391 | noisespeedx = 0;
392 | noisespeedy = 1;
393 | noisespeedz = 0;
394 | noisescale = 10; //20
395 | colorLoop = 0;
396 | return drawNoise(calbayo_15_gp);
397 | }
398 | //===============================================
399 | uint16_t CoralReef() {
400 | noisespeedx = 1;
401 | noisespeedy = 0;
402 | noisespeedz = 1;
403 | noisescale = 25; //20
404 | colorLoop = 0;
405 | return drawNoise(Coral_reef_gp);
406 | }
407 | //===============================================
408 | uint16_t Vintage1() {
409 | noisespeedx = 1;
410 | noisespeedy = 1;
411 | noisespeedz = 0;
412 | noisescale = 12; //20
413 | colorLoop = 0;
414 | return drawNoise(es_vintage_01_gp);
415 | }
416 | //===============================================
417 | uint16_t Vintage49() {
418 | noisespeedx = 1;
419 | noisespeedy = 1;
420 | noisespeedz = 0;
421 | noisescale = 12; //20
422 | colorLoop = 0;
423 | return drawNoise(es_vintage_49_gp);
424 | }
425 | //===============================================
426 | uint16_t Analogous1() {
427 | noisespeedx = 1;
428 | noisespeedy = 1;
429 | noisespeedz = 0;
430 | noisescale = 18; //20
431 | colorLoop = 0;
432 | return drawNoise(Analogous_1_gp);
433 | }
--------------------------------------------------------------------------------
/Pulse.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Torch: https://github.com/evilgeniuslabs/torch
3 | * Copyright (C) 2015 Jason Coon
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | uint16_t Pulse() {
20 | // palette = RainbowColors_p;
21 |
22 | static uint8_t hue = 0;
23 | static uint8_t centerX = 0;
24 | static uint8_t centerY = 0;
25 | static uint8_t step = 0;
26 |
27 | static const uint8_t maxSteps = 16;
28 | static const float fadeRate = 0.8;
29 |
30 | dimAll(235);
31 |
32 | if (step == 0) {
33 | centerX = random(32);
34 | centerY = random(32);
35 | hue = random(256); // 170;
36 |
37 | drawCircle(centerX, centerY, step, ColorFromPalette(palette, hue));
38 | step++;
39 | }
40 | else {
41 | if (step < maxSteps) {
42 | // initial pulse
43 | drawCircle(centerX, centerY, step, ColorFromPalette(palette, hue, pow(fadeRate, step - 2) * 255));
44 |
45 | // secondary pulse
46 | if (step > 3) {
47 | drawCircle(centerX, centerY, step - 3, ColorFromPalette(palette, hue, pow(fadeRate, step - 2) * 255));
48 | }
49 | step++;
50 | }
51 | else {
52 | step = 0;
53 | }
54 | }
55 |
56 | return 30;
57 | }
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LED Effect Lamp For PJRC Teensy / WS2812B Matrix
2 | ### PROJECT HAS BEEN MOVED TO: https://github.com/MakingThingsWithLEDs/FlameAndEffectLampProject
3 |
4 | | Fire Lamp | Lava / Plasma Lamp | Sound Reactive | Other Effects |
5 | | --------------------------------- | ----------------------------- | ------------------------- | --------------------- |
6 | | TorchBlue | BlackAndWhite | AudioAnalyzerColumns | BlackAndWhiteNoise|
7 | | TorchChemical | Cloud | AudioAnalyzerColumnsSolid | BPM|
8 | | TorchGreen | Forest | AudioAnalyzerPixels | CloudTwinkles|
9 | | TorchOrange | Lava | AudioBlackAndBlue | ColorWaves|
10 | | TorchPurple | Ocean | AudioBlackAndWhite | Confetti|
11 | | | Party | AudioCloud | Fire2012WithPalette|
12 | | TorchRed | Rainbow | AudioFallingSpectrogram | Fireflies|
13 | | TorchWhite | RainbowStripe | AudioFire1 | FireNoise|
14 | | | Spectrum | AudioFire2 | HueCycle|
15 | | | | Temperature | AudioFire3 | IncandescentTwinkles|
16 | | | RampRGB | AudioForest | Juggle|
17 | | | ColorCube | AudioLava | Pride|
18 | | | Curvature | AudioLavaMagenta | Pulse|
19 | | | Shikon1 | AudioLavaRainbow | Rainbow|
20 | | | Shikon2 | AudioOcean | RainbowTwinkles|
21 | | | Slope | AudioParty | RainbowWithGlitter|
22 | | | | AudioRainbowStripe | SolidColor|
23 | | | | | Sinelon|
24 | | | | | SnowTwinkles|
25 | | | | | Wave|
26 |
27 | ### Support
28 | **Project:** https://www.youtube.com/playlist?list=PLuTvWrqvrCQGxWSenKpJilgakO-iD05nO
29 |
30 | 
31 | https://youtube.com/shorts/MAVUOS6Amuc?feature=share
32 |
--------------------------------------------------------------------------------
/VariableList.txt:
--------------------------------------------------------------------------------
1 | cycle_wait6
2 | flame_min6
3 | flame_max6
4 | random_spark_probability8
5 | spark_min8
6 | spark_max8
7 | spark_tfr8
8 | spark_cap8
9 | up_rad8
10 | side_rad8
11 | heat_cap8
12 | red_bg8
13 | green_bg8
14 | blue_bg8
15 | red_bias8
16 | green_bias8
17 | blue_bias8
18 | red_energy8
19 | green_energy8
20 | blue_energy8
21 | upside_down8
22 | currentEnergy8
23 | nextEnergy8
24 | energyMode8
25 | torch_passive8
26 | torch_nop8
27 | torch_spark8
28 | reduce8
29 | increase8
30 | random8
31 | resetEnergy8
32 | energymap8
33 | injectrandom8
34 | calcNextColors8
--------------------------------------------------------------------------------
/Wave.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Torch: https://github.com/evilgeniuslabs/torch
3 | * Copyright (C) 2015 Jason Coon
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program. If not, see .
17 | */
18 |
19 | uint16_t Wave() {
20 | static byte rotation = 3;
21 |
22 | static const uint8_t scaleWidth = 256 / MATRIX_WIDTH;
23 | static const uint8_t scaleHeight = 256 / MATRIX_HEIGHT;
24 |
25 | static const uint8_t maxX = MATRIX_WIDTH - 1;
26 | static const uint8_t maxY = MATRIX_HEIGHT - 1;
27 |
28 | static uint8_t waveCount = 1;
29 | static uint8_t hue = 1;
30 | static uint8_t theta = 0;
31 |
32 | // EVERY_N_SECONDS(10) {
33 | // rotation = random(0, 1);
34 | // waveCount = random(1, 3);
35 | // }
36 |
37 | int n = 0;
38 |
39 | switch (rotation) {
40 | case 0:
41 | for (int x = 0; x < MATRIX_WIDTH; x++) {
42 | n = quadwave8(x * 2 + theta) / scaleHeight;
43 | leds[XY(x, n)] = ColorFromPalette(palette, x + hue);
44 | if (waveCount == 2)
45 | leds[XY(x, maxY - n)] = ColorFromPalette(palette, x + hue);
46 | }
47 | break;
48 |
49 | case 1:
50 | for (int y = 0; y < MATRIX_HEIGHT; y++) {
51 | n = quadwave8(y * 2 + theta) / scaleWidth;
52 | leds[XY(n, y)] = ColorFromPalette(palette, y + hue);
53 | if (waveCount == 2)
54 | leds[XY(maxX - n, y)] = ColorFromPalette(palette, y + hue);
55 | }
56 | break;
57 |
58 | case 2:
59 | for (int x = 0; x < MATRIX_WIDTH; x++) {
60 | n = quadwave8(x * 2 - theta) / scaleHeight;
61 | leds[XY(x, n)] = ColorFromPalette(palette, x + hue);
62 | if (waveCount == 2)
63 | leds[XY(x, maxY - n)] = ColorFromPalette(palette, x + hue);
64 | }
65 | break;
66 |
67 | case 3:
68 | for (int y = 0; y < MATRIX_HEIGHT; y++) {
69 | n = quadwave8(y * 2 - theta) / scaleWidth;
70 | leds[XY(n, y)] = ColorFromPalette(palette, y + hue);
71 | if (waveCount == 2)
72 | leds[XY(maxX - n, y)] = ColorFromPalette(palette, y + hue);
73 | }
74 | break;
75 | }
76 |
77 | dimAll(254);
78 |
79 | EVERY_N_MILLISECONDS(10) {
80 | theta++;
81 | hue++;
82 | }
83 |
84 | return 0;
85 | }
86 |
--------------------------------------------------------------------------------