Skip to content

Commit 6f5783d

Browse files
authoredApr 17, 2021
Minor tweaks to the lib, and enhancements to custom effects and example sketches (kitesurfer1404#283)
* Minor tweaks to the lib, and enhancments to custom effects and example sketches. * Added audio reactive example sketch * fixed a typo * Updated documentation
1 parent 4774866 commit 6f5783d

22 files changed

+4653
-927
lines changed
 

‎README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ Effects
126126
52. **Halloween** - Alternating orange/purple pixels running.
127127
53. **Bicolor Chase** - Two LEDs running on a background color.
128128
54. **Tricolor Chase** - Alternating three color pixels running.
129-
55. thru 62. **Custom** - Up to eight user created custom effects.
129+
55. **TwinkleFOX** - Lights fading in and out randomly.
130+
56. thru 63. **Custom** - Up to eight user created custom effects.
130131
131132
132133
Projects using WS2812FX

‎examples/esp8266_webinterface/esp8266_webinterface.ino

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ unsigned long auto_last_change = 0;
7575
unsigned long last_wifi_check_time = 0;
7676
String modes = "";
7777
uint8_t myModes[] = {}; // *** optionally create a custom list of effect/mode numbers
78-
boolean auto_cycle = false;
78+
bool auto_cycle = false;
7979

8080
WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
8181
ESP8266WebServer server(HTTP_PORT);

‎examples/serial_control/serial_control.ino

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
5050
WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
5151

52-
char cmd[MAX_NUM_CHARS]; // char[] to store incoming serial commands
53-
boolean cmd_complete = false; // whether the command string is complete
52+
char cmd[MAX_NUM_CHARS]; // char[] to store incoming serial commands
53+
bool cmd_complete = false; // whether the command string is complete
5454

5555
void setup() {
5656
Serial.begin(115200);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
WS2812FX example sketch to demo sound reactivity
3+
4+
Keith Lord - 2021
5+
6+
FEATURES
7+
* use an audio sensor (like those commonly made with an LM393 chip) to add
8+
sound reactivity to your LED lights. Connect the audio output of the sound
9+
detector (AO) to your microprocessor's analog input.
10+
11+
* https://electropeak.com/learn/interfacing-ky-037-sound-sensor-with-arduino/
12+
13+
14+
LICENSE
15+
16+
The MIT License (MIT)
17+
18+
Copyright (c) 2021 Keith Lord
19+
20+
Permission is hereby granted, free of charge, to any person obtaining a copy
21+
of this software and associated documentation files (the "Software"), to deal
22+
in the Software without restriction, including without limitation the rights
23+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24+
copies of the Software, and to permit persons to whom the Software is
25+
furnished to do so, subject to the following conditions:
26+
27+
The above copyright notice and this permission notice shall be included in
28+
all copies or substantial portions of the Software.
29+
30+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36+
THE SOFTWARE.
37+
38+
39+
CHANGELOG
40+
2021-04-02 initial version
41+
42+
*/
43+
44+
#include <WS2812FX.h>
45+
46+
#define LED_PIN 4 // digital pin used to drive the LED strip
47+
#define LED_COUNT 144 // number of LEDs on the strip
48+
49+
#define MIN_BRIGHTNESS 1
50+
#define MAX_BRIGHTNESS 255
51+
#define THRESHOLD 5
52+
53+
WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
54+
55+
uint16_t quietLevel = 0;
56+
uint16_t maxSample = 0;
57+
uint16_t maxSampleEver = 0;
58+
unsigned long timer = 0;
59+
60+
void setup() {
61+
Serial.begin(115200);
62+
63+
// take some initial audio measurements to establish the "quiet" level
64+
for(int i=0; i<20; i++) {
65+
quietLevel += analogRead(A0); // 0-1023
66+
delay(25);
67+
}
68+
quietLevel /= 20;
69+
Serial.print("\nquietLevel is "); Serial.println(quietLevel);
70+
71+
ws2812fx.init();
72+
ws2812fx.setBrightness(64);
73+
74+
// parameters: index, start, stop, mode, color, speed, reverse
75+
ws2812fx.setSegment(0, 0, LED_COUNT-1, FX_MODE_STATIC, RED, 8000, NO_OPTIONS);
76+
77+
ws2812fx.start();
78+
}
79+
80+
void loop() {
81+
// take an audio sample
82+
uint16_t audioSample = abs(analogRead(A0) - quietLevel);
83+
if(audioSample > maxSample) maxSample = audioSample;
84+
85+
// if the timer has expired, use the sampled audio to recalculate the LED brightness
86+
if(millis() > timer) {
87+
if(maxSample > THRESHOLD) { // ensure the audio is above the threshold to reduce LED flickering
88+
if(maxSample > maxSampleEver) maxSampleEver = maxSample;
89+
90+
// calculate a new brightness, properly scaled to the sampled audio
91+
uint8_t newBrightness = map(maxSample, THRESHOLD, maxSampleEver, MIN_BRIGHTNESS, MAX_BRIGHTNESS);
92+
// Serial.print("maxSample:");Serial.print(maxSample); // debug
93+
// Serial.print(", maxSampleEver:");Serial.print(maxSampleEver);
94+
// Serial.print(", newBrightness:");Serial.println(newBrightness);
95+
ws2812fx.setBrightness(newBrightness);
96+
} else {
97+
ws2812fx.setBrightness(MIN_BRIGHTNESS);
98+
}
99+
100+
maxSample = 0;
101+
timer = millis() + 100; // recalc brightness every 100ms
102+
}
103+
104+
ws2812fx.service();
105+
}

‎examples/ws2812fx_limit_current/ws2812fx_limit_current.ino

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@
5252
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
5353
WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
5454

55-
char cmd[MAX_NUM_CHARS]; // char[] to store incoming serial commands
56-
boolean cmd_complete = false; // whether the command string is complete
55+
char cmd[MAX_NUM_CHARS]; // char[] to store incoming serial commands
56+
bool cmd_complete = false; // whether the command string is complete
5757

5858
void setup() {
5959
Serial.begin(115200);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Adafruit_NeoMatrix example for single NeoPixel Shield.
2+
// Scrolls 'Howdy' across the matrix in a portrait (vertical) orientation.
3+
4+
#include <Adafruit_GFX.h>
5+
#include <Adafruit_NeoMatrix.h>
6+
#include <Adafruit_NeoPixel.h>
7+
#ifndef PSTR
8+
#define PSTR // Make Arduino Due happy
9+
#endif
10+
11+
#define PIN D5
12+
13+
// MATRIX DECLARATION:
14+
// Parameter 1 = width of NeoPixel matrix
15+
// Parameter 2 = height of matrix
16+
// Parameter 3 = pin number (most are valid)
17+
// Parameter 4 = matrix layout flags, add together as needed:
18+
// NEO_MATRIX_TOP, NEO_MATRIX_BOTTOM, NEO_MATRIX_LEFT, NEO_MATRIX_RIGHT:
19+
// Position of the FIRST LED in the matrix; pick two, e.g.
20+
// NEO_MATRIX_TOP + NEO_MATRIX_LEFT for the top-left corner.
21+
// NEO_MATRIX_ROWS, NEO_MATRIX_COLUMNS: LEDs are arranged in horizontal
22+
// rows or in vertical columns, respectively; pick one or the other.
23+
// NEO_MATRIX_PROGRESSIVE, NEO_MATRIX_ZIGZAG: all rows/columns proceed
24+
// in the same order, or alternate lines reverse direction; pick one.
25+
// See example below for these values in action.
26+
// Parameter 5 = pixel type flags, add together as needed:
27+
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
28+
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
29+
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
30+
// NEO_GRBW Pixels are wired for GRBW bitstream (RGB+W NeoPixel products)
31+
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
32+
33+
34+
// Example for NeoPixel Shield. In this application we'd like to use it
35+
// as a 5x8 tall matrix, with the USB port positioned at the top of the
36+
// Arduino. When held that way, the first pixel is at the top right, and
37+
// lines are arranged in columns, progressive order. The shield uses
38+
// 800 KHz (v2) pixels that expect GRB color data.
39+
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(5, 8, PIN,
40+
NEO_MATRIX_TOP + NEO_MATRIX_RIGHT +
41+
NEO_MATRIX_COLUMNS + NEO_MATRIX_PROGRESSIVE,
42+
NEO_GRB + NEO_KHZ800);
43+
44+
45+
int16_t x = matrix.width();
46+
uint8_t color_index = 0;
47+
char text[] = "Howdy";
48+
int scroll_limit = sizeof(text) * 6; // each text character is 6 pixels wide
49+
50+
void setup() {
51+
matrix.begin();
52+
matrix.setTextWrap(false);
53+
matrix.setBrightness(40);
54+
matrix.setTextColor(matrix.Color(255, 0, 0)); // default color is red
55+
}
56+
57+
void loop() {
58+
matrix.fillScreen(0);
59+
matrix.setCursor(x, 0);
60+
matrix.print(text);
61+
62+
if(--x < -scroll_limit) {
63+
x = matrix.width();
64+
color_index = 0; // reset the rainbow color index
65+
}
66+
matrix.setTextColor(color_wheel(color_index));
67+
color_index += max(1, 256 / scroll_limit);
68+
matrix.show();
69+
delay(100);
70+
}
71+
72+
uint16_t color_wheel(uint8_t pos) {
73+
pos = 255 - pos;
74+
if(pos < 85) {
75+
// return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3);
76+
return matrix.Color((uint16_t)(255 - pos * 3), 0, (pos * 3));
77+
} else if(pos < 170) {
78+
pos -= 85;
79+
// return ((uint32_t)(0) << 16) | ((uint32_t)(pos * 3) << 8) | (255 - pos * 3);
80+
return matrix.Color(0, (uint32_t)(pos * 3), (255 - pos * 3));
81+
} else {
82+
pos -= 170;
83+
// return ((uint32_t)(pos * 3) << 16) | ((uint32_t)(255 - pos * 3) << 8) | (0);
84+
return matrix.Color((uint16_t)(pos * 3), (uint32_t)(255 - pos * 3), 0);
85+
}
86+
}
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include <pgmspace.h>
2+
3+
#ifndef _APP_CSS_
4+
#define _APP_CSS_
5+
6+
const char app_css[] PROGMEM = R"=====(
7+
/* tweaks for Material Design Components */
8+
body {
9+
margin: 0; /* remove the default 8px body margin to fix MDC top-app-bar placement */
10+
/* --mdc-theme-primary: #3fb8af; */ /* change MDC color theme to match noUiSlide's theme */
11+
}
12+
.mdc-top-app-bar { /* force the top bar text color to white */
13+
color: #ffffff;
14+
}
15+
main, .mdc-switch {
16+
margin: 0px 8px; /* add a little margin the MDC switches */
17+
}
18+
h3 {
19+
margin: 4px 0px; /* add a little margin to the widget labels */
20+
}
21+
/* MDC select and text-field labels are hardcoded to purple??? reset to primary color */
22+
/* .mdc-select:not(.mdc-select--disabled).mdc-select--focused .mdc-floating-label {
23+
color: var(--mdc-theme-primary, #3fb8af)
24+
}
25+
.mdc-text-field--focused:not(.mdc-text-field--disabled) .mdc-floating-label {
26+
color: var(--mdc-theme-primary, #3fb8af);
27+
} */
28+
.mdc-list, div.border { /* add border around MDC lists */
29+
border: 1px solid rgba(0, 0, 0, 0.1);
30+
padding: 0px;
31+
}
32+
.mdc-list-item { /* make list items a little shorter (default is 48px) */
33+
height: 32px;
34+
}
35+
.mdc-button { /* add margin-bottom to buttons so they wrap properly on small screens */
36+
margin-bottom: 8px;
37+
}
38+
.noUi-tooltip { /* only show slider tooltips when the slider is being moved */
39+
display: none;
40+
}
41+
.noUi-active .noUi-tooltip {
42+
display: block;
43+
}
44+
footer {
45+
margin: 4px 16px; /* add a little margin to the footer content */
46+
}
47+
48+
div.fine-border { /* add a border */
49+
border: 1px solid rgba(0, 0, 0, 0.1);
50+
padding: 4px 16px;
51+
}
52+
)=====";
53+
#endif

‎examples/ws2812fx_segments_web/app.js.h

+528
Large diffs are not rendered by default.

‎examples/ws2812fx_segments_web/bundle.css.h

+955
Large diffs are not rendered by default.

‎examples/ws2812fx_segments_web/bundle.js.h

+2,065
Large diffs are not rendered by default.

‎examples/ws2812fx_segments_web/index.html.cpp

-661
This file was deleted.
+359
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
#include <pgmspace.h>
2+
3+
#ifndef _INDEX_HTML_
4+
#define _INDEX_HTML_
5+
6+
const char index_html[] PROGMEM = R"=====(
7+
<!DOCTYPE html>
8+
<html>
9+
10+
<head>
11+
<meta charset="UTF-8">
12+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
13+
14+
<!-- <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> -->
15+
<!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nouislider@14.6.4/distribute/nouislider.min.css"> -->
16+
<!-- <link rel="stylesheet" href="https://unpkg.com/material-components-web@3.2.0/dist/material-components-web.min.css"> -->
17+
<link rel="stylesheet" href="/bundle.css">
18+
<link rel="stylesheet" href="/app.css">
19+
20+
<style>
21+
/* CSS for local Google Material Icons */
22+
@font-face {
23+
font-family: 'Material Icons';
24+
font-style: normal;
25+
font-weight: 400;
26+
src: url(/Material-Icons-subset.woff2) format('woff2');
27+
}
28+
29+
.material-icons {
30+
font-family: 'Material Icons';
31+
font-weight: normal;
32+
font-style: normal;
33+
font-size: 24px;
34+
line-height: 1;
35+
letter-spacing: normal;
36+
text-transform: none;
37+
display: inline-block;
38+
white-space: nowrap;
39+
word-wrap: normal;
40+
direction: ltr;
41+
-webkit-font-feature-settings: 'liga';
42+
font-feature-settings: 'liga';
43+
-webkit-font-smoothing: antialiased;
44+
}
45+
</style>
46+
</head>
47+
48+
<body class="mdc-typography">
49+
50+
<!-- <header class="mdc-top-app-bar"> -->
51+
<header class="mdc-top-app-bar mdc-top-app-bar--dense">
52+
<div class="mdc-top-app-bar__row">
53+
<section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-start">
54+
<span class="mdc-top-app-bar__title">WS2812FX Web Interface</span>
55+
</section>
56+
</div>
57+
</header>
58+
59+
<main class="mdc-top-app-bar--dense-fixed-adjust">
60+
61+
<div id="mdc-snackbar" class="mdc-snackbar">
62+
<div class="mdc-snackbar__surface" role="status" aria-relevant="additions">
63+
<div class="mdc-snackbar__label" aria-atomic="false">
64+
Error connecting to your ESP. Make sure it's turned on, then refresh the browser.
65+
</div>
66+
</div>
67+
</div>
68+
69+
<div class="mdc-layout-grid">
70+
71+
<div class="mdc-layout-grid__inner">
72+
<div class="mdc-layout-grid__cell mdc-layout-grid__cell--span-12">
73+
<div id="mdc-select-preset" class="mdc-select mdc-select--outlined">
74+
<i class="mdc-select__dropdown-icon"></i>
75+
<select id="presetSelect" class="mdc-select__native-control">
76+
<option value="0" selected>Default</option>
77+
</select>
78+
<div class="mdc-notched-outline">
79+
<div class="mdc-notched-outline__leading"></div>
80+
<div class="mdc-notched-outline__notch">
81+
<label class="mdc-floating-label mdc-floating-label--float-above">Presets</label>
82+
</div>
83+
<div class="mdc-notched-outline__trailing"></div>
84+
</div>
85+
</div>
86+
87+
<button id="mdc-button-copyPreset" class="mdc-button mdc-button--raised">
88+
<i class="material-icons mdc-button__icon" aria-hidden="true">content_copy</i>
89+
<span class="mdc-button__label">Copy Preset</span>
90+
</button>
91+
<button id="mdc-button-deletePreset" class="mdc-button mdc-button--raised">
92+
<i class="material-icons mdc-button__icon" aria-hidden="true">delete</i>
93+
<span class="mdc-button__label">Delete Preset</span>
94+
</button>
95+
96+
<button id="mdc-button-savePreset" class="mdc-button mdc-button--raised">
97+
<i class="material-icons mdc-button__icon" aria-hidden="true">save</i>
98+
<span class="mdc-button__label">Save Presets</span>
99+
</button>
100+
</div>
101+
</div>
102+
<hr />
103+
104+
<div class="mdc-layout-grid__inner">
105+
<div class="mdc-layout-grid__cell mdc-layout-grid__cell--span-6">
106+
<p>
107+
<label id="mdc-text-field-numPixels" class="mdc-text-field mdc-text-field--outlined">
108+
<span class="mdc-notched-outline">
109+
<span class="mdc-notched-outline__leading"></span>
110+
<span class="mdc-notched-outline__notch">
111+
<span class="mdc-floating-label" id="numPixelsTextLabel">Number of Pixels</span>
112+
</span>
113+
<span class="mdc-notched-outline__trailing"></span>
114+
</span>
115+
<input type="text" class="mdc-text-field__input" aria-labelledby="numPixelsTextLabel" value="30">
116+
</label>
117+
118+
<label id="mdc-text-field-pin" class="mdc-text-field mdc-text-field--outlined">
119+
<span class="mdc-notched-outline">
120+
<span class="mdc-notched-outline__leading"></span>
121+
<span class="mdc-notched-outline__notch">
122+
<span class="mdc-floating-label" id="pinTextLabel">GPIO Pin</span>
123+
</span>
124+
<span class="mdc-notched-outline__trailing"></span>
125+
</span>
126+
<input type="text" class="mdc-text-field__input" aria-labelledby="pinTextLabel" value="4">
127+
</label>
128+
</p>
129+
130+
<p>
131+
<h3 class="mdc-typography--subtitle1">Brightness</h3>
132+
<div id="brightnessSlider"></div>
133+
</p>
134+
135+
<p>
136+
<h2 class="mdc-typography--subtitle1">Segments</h2>
137+
<ul id="mdc-list-segment" class="mdc-list" role="listbox"></ul>
138+
</p>
139+
140+
<p>
141+
<button id="mdc-button-addSegment" class="mdc-button mdc-button--raised">
142+
<i class="material-icons mdc-button__icon" aria-hidden="true">add</i>
143+
<span class="mdc-button__label">Add Segment</span>
144+
</button>
145+
<button id="mdc-button-showCode" class="mdc-button mdc-button--raised">
146+
<i class="material-icons mdc-button__icon" aria-hidden="true">code</i>
147+
<span class="mdc-button__label">Show Code</span>
148+
</button>
149+
</p>
150+
</div>
151+
152+
<div class="mdc-layout-grid__cell mdc-layout-grid__cell--span-6 fine-border">
153+
<p>
154+
<h3 class="mdc-typography--subtitle1">Segment Range</h3>
155+
<div id="rangeSlider"></div>
156+
</p>
157+
158+
<p>
159+
<h3 class="mdc-typography--subtitle1">Segment Speed</h3>
160+
<div id="speedSlider"></div>
161+
</p>
162+
163+
<div class="mdc-layout-grid__inner">
164+
<div class="mdc-layout-grid__cell mdc-layout-grid__cell--span-6">
165+
<p>
166+
<h3 class="mdc-typography--subtitle1" style="display: inline-block">Colors</h3>
167+
<input type="color" id="color0">
168+
<input type="color" id="color1">
169+
<input type="color" id="color2">
170+
</p>
171+
172+
<p>
173+
<h3 class="mdc-typography--subtitle1" style="display: inline-block">Reverse</h3>
174+
<div id="mdc-switch-reverse" class="mdc-switch">
175+
<div class="mdc-switch__track"></div>
176+
<div class="mdc-switch__thumb-underlay">
177+
<div class="mdc-switch__thumb">
178+
<input type="checkbox" id="reverse" class="mdc-switch__native-control" role="switch">
179+
</div>
180+
</div>
181+
</div>
182+
<label for="reverse">off/on</label>
183+
</p>
184+
185+
<p>
186+
<h3 class="mdc-typography--subtitle1" style="display: inline-block">Gamma Correction</h3>
187+
<div id="mdc-switch-gamma" class="mdc-switch">
188+
<div class="mdc-switch__track"></div>
189+
<div class="mdc-switch__thumb-underlay">
190+
<div class="mdc-switch__thumb">
191+
<input type="checkbox" id="gamma" class="mdc-switch__native-control" role="switch">
192+
</div>
193+
</div>
194+
</div>
195+
<label for="gamma">off/on</label>
196+
</p>
197+
</div>
198+
199+
<div class="mdc-layout-grid__cell mdc-layout-grid__cell--span-6">
200+
<p>
201+
<div id="mdc-select-mode" class="mdc-select mdc-select--outlined">
202+
<i class="mdc-select__dropdown-icon"></i>
203+
<select class="mdc-select__native-control">
204+
<option value="0">Static</option>
205+
</select>
206+
<div class="mdc-notched-outline">
207+
<div class="mdc-notched-outline__leading"></div>
208+
<div class="mdc-notched-outline__notch">
209+
<label class="mdc-floating-label mdc-floating-label--float-above">Segment Mode</label>
210+
</div>
211+
<div class="mdc-notched-outline__trailing"></div>
212+
</div>
213+
</div>
214+
</p>
215+
216+
<p>
217+
<div id="mdc-select-fade" class="mdc-select mdc-select--outlined">
218+
<i class="mdc-select__dropdown-icon"></i>
219+
<select class="mdc-select__native-control">
220+
<option value="0" selected>Default</option>
221+
<option value="1">XFAST</option>
222+
<option value="2">FAST</option>
223+
<option value="3">MEDIUM</option>
224+
<option value="4">SLOW</option>
225+
<option value="5">XSLOW</option>
226+
<option value="6">XXSLOW</option>
227+
<option value="7">GLACIAL</option>
228+
</select>
229+
<div class="mdc-notched-outline">
230+
<div class="mdc-notched-outline__leading"></div>
231+
<div class="mdc-notched-outline__notch">
232+
<label class="mdc-floating-label mdc-floating-label--float-above">Fade Rate</label>
233+
</div>
234+
<div class="mdc-notched-outline__trailing"></div>
235+
</div>
236+
</div>
237+
</p>
238+
239+
<p>
240+
<div id="mdc-select-size" class="mdc-select mdc-select--outlined">
241+
<i class="mdc-select__dropdown-icon"></i>
242+
<select class="mdc-select__native-control">
243+
<option value="0" selected>SMALL</option>
244+
<option value="1">MEDIUM</option>
245+
<option value="2">LARGE</option>
246+
<option value="3">XLARGE</option>
247+
</select>
248+
<div class="mdc-notched-outline">
249+
<div class="mdc-notched-outline__leading"></div>
250+
<div class="mdc-notched-outline__notch">
251+
<label class="mdc-floating-label mdc-floating-label--float-above">Size</label>
252+
</div>
253+
<div class="mdc-notched-outline__trailing"></div>
254+
</div>
255+
</div>
256+
</p>
257+
258+
</div>
259+
</div>
260+
</div>
261+
</div>
262+
263+
<div class="mdc-layout-grid__inner">
264+
<div class="mdc-layout-grid__cell mdc-layout-grid__cell--span-12">
265+
<div id="mdc-switch-power" class="mdc-switch mdc-switch--checked">
266+
<div class="mdc-switch__track"></div>
267+
<div class="mdc-switch__thumb-underlay">
268+
<div class="mdc-switch__thumb">
269+
<input type="checkbox" id="powerSwitch" class="mdc-switch__native-control" role="switch" checked>
270+
</div>
271+
</div>
272+
</div>
273+
<label for="powerSwitch" style="margin-right:20px;">LEDs off/on</label>
274+
275+
<div id="mdc-switch-play" class="mdc-switch mdc-switch--checked">
276+
<div class="mdc-switch__track"></div>
277+
<div class="mdc-switch__thumb-underlay">
278+
<div class="mdc-switch__thumb">
279+
<input type="checkbox" id="playSwitch" class="mdc-switch__native-control" role="switch" checked>
280+
</div>
281+
</div>
282+
</div>
283+
<label for="playSwitch">LEDs pause/play</label>
284+
</div>
285+
</div>
286+
</div>
287+
288+
</main>
289+
290+
<footer>
291+
<div>&copy; 2021
292+
<span>Made with
293+
<a href="https://material.io/develop/web/">Material Components for the Web</a>
294+
</span>
295+
</div>
296+
</footer>
297+
298+
<!-- Code dialog -->
299+
<div id="mdc-dialog-code" class="mdc-dialog" role="alertdialog" aria-modal="true" aria-labelledby="code-dialog-title" aria-describedby="code-dialog-content">
300+
<div class="mdc-dialog__container">
301+
<div class="mdc-dialog__surface">
302+
<h2 class="mdc-dialog__title" id="code-dialog-title">ESP8266/Arduino Code</h2>
303+
<section class="mdc-dialog__content" id="code-dialog-content">
304+
<textarea id="codeDialogContent" rows="15" cols="60"></textarea>
305+
</section>
306+
307+
<footer class="mdc-dialog__actions">
308+
<button id="mdc-button-copyCode" type="button" class="mdc-button mdc-dialog__button mdc-button--raised" data-mdc-dialog-action="copy">
309+
<span class="mdc-button__label">Copy To Clipboard</span>
310+
</button>
311+
<button type="button" class="mdc-button mdc-dialog__button mdc-button--raised" data-mdc-dialog-action="close">
312+
<span class="mdc-button__label">Close</span>
313+
</button>
314+
</footer>
315+
</div>
316+
</div>
317+
<div class="mdc-dialog__scrim"></div>
318+
</div>
319+
320+
<!-- Preset name dialog -->
321+
<div id="mdc-dialog-presetName" class="mdc-dialog" role="alertdialog" aria-modal="true" aria-labelledby="presetName-dialog-title" aria-describedby="presetName-dialog-content">
322+
<div class="mdc-dialog__container">
323+
<div class="mdc-dialog__surface">
324+
<h2 class="mdc-dialog__title" id="presetName-dialog-title">Enter a preset name</h2>
325+
<section class="mdc-dialog__content" id="presetName-dialog-content">
326+
<label id="mdc-text-field-presetName" class="mdc-text-field mdc-text-field--outlined mdc-text-field--no-label">
327+
<span class="mdc-notched-outline">
328+
<span class="mdc-notched-outline__leading"></span>
329+
<span class="mdc-notched-outline__trailing"></span>
330+
</span>
331+
<input type="text" class="mdc-text-field__input" aria-label="Label" value="">
332+
</label>
333+
</section>
334+
335+
<footer class="mdc-dialog__actions">
336+
<button id="mdc-button-presetName" type="button" class="mdc-button mdc-dialog__button mdc-button--raised" data-mdc-dialog-action="ok">
337+
<span class="mdc-button__label">OK</span>
338+
</button>
339+
<button type="button" class="mdc-button mdc-dialog__button mdc-button--raised" data-mdc-dialog-action="close">
340+
<span class="mdc-button__label">Cancel</span>
341+
</button>
342+
</footer>
343+
344+
</div>
345+
</div>
346+
<div class="mdc-dialog__scrim"></div>
347+
</div>
348+
349+
<!-- <script src="https://cdn.jsdelivr.net/npm/nouislider@14.6.4/distribute/nouislider.min.js"></script> -->
350+
<!-- <script src="https://unpkg.com/material-components-web@3.2.0/dist/material-components-web.min.js"></script> -->
351+
<script src="/bundle.js"></script>
352+
<script src="/app.js"></script>
353+
354+
<!-- <script>window.mdc.autoInit();</script> -->
355+
</body>
356+
357+
</html>
358+
)=====";
359+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include <pgmspace.h>
2+
3+
// A custom, abreviated version of Material+Icon font.
4+
// It only contains these icons: content_copy delete file_download save add code and was
5+
// created with this fonttools command:
6+
// fonttools subset MaterialIcons-Regular.ttf --unicodes=5f-7a,30-39,e14d,e872,e2c4,e161,e145,e86f --no-layout-closure --output-file=material-icons-subset.woff2 --flavor=woff2
7+
// See https://pypi.org/project/fonttools/
8+
// and https://stackoverflow.com/questions/64614572/creating-a-material-icons-subset
9+
10+
#ifndef _MATERIAL_ICONS_SUBSET_
11+
#define _MATERIAL_ICONS_SUBSET_
12+
13+
const uint8_t material_icons_subset[] PROGMEM = {
14+
0x77, 0x4F, 0x46, 0x32, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x90, 0x00, 0x0F, 0x00, 0x00,
15+
0x00, 0x00, 0x0A, 0x04, 0x00, 0x00, 0x03, 0x3B, 0x00, 0x01, 0x02, 0xD0, 0x00, 0x00, 0x00, 0x00,
16+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17+
0x1A, 0x1C, 0x1B, 0x10, 0x1C, 0x81, 0x4C, 0x06, 0x60, 0x00, 0x81, 0x78, 0x08, 0x04, 0x11, 0x08,
18+
0x0A, 0x87, 0x5C, 0x84, 0x1A, 0x01, 0x36, 0x02, 0x24, 0x03, 0x5A, 0x0B, 0x5A, 0x00, 0x04, 0x20,
19+
0x05, 0x82, 0x7A, 0x07, 0x20, 0x1B, 0xE3, 0x06, 0x00, 0x2E, 0x0B, 0x78, 0x43, 0xFA, 0xE8, 0x39,
20+
0x84, 0x17, 0xE8, 0x94, 0x54, 0x8D, 0x21, 0x36, 0x5F, 0x5D, 0x81, 0xAA, 0x3B, 0x75, 0xD8, 0xFA,
21+
0x5A, 0x22, 0x78, 0x7E, 0xAE, 0x9C, 0xF7, 0x93, 0xA3, 0x6C, 0x0E, 0xA1, 0x8C, 0xA0, 0x2A, 0x81,
22+
0x40, 0x89, 0x2A, 0xC9, 0xAE, 0xAC, 0x4E, 0x98, 0xD6, 0xEE, 0xC1, 0xE5, 0xAE, 0xB5, 0x31, 0x7D,
23+
0x6C, 0x53, 0xB8, 0xE8, 0xB3, 0xB7, 0xA9, 0x63, 0x2E, 0xEE, 0x35, 0xC4, 0x28, 0x1D, 0x58, 0x0C,
24+
0x06, 0xD7, 0xA6, 0x8B, 0x2C, 0xB8, 0xE1, 0x44, 0x3B, 0x6C, 0xFB, 0x4F, 0xB7, 0x7A, 0x69, 0x51,
25+
0x89, 0x35, 0x5F, 0xA0, 0x38, 0x3E, 0x2E, 0x3A, 0x39, 0xD0, 0xC2, 0x09, 0xA8, 0xF8, 0xB8, 0x41,
26+
0xCE, 0xD5, 0x05, 0x5F, 0x5B, 0xDB, 0x9D, 0xEA, 0x48, 0x6D, 0xC0, 0x5F, 0xE5, 0x66, 0xF9, 0xEF,
27+
0x3F, 0x38, 0xFD, 0xBD, 0xD3, 0x3F, 0x56, 0xED, 0xF3, 0x68, 0x2E, 0x82, 0x84, 0x3A, 0x8F, 0xD7,
28+
0xC0, 0x39, 0x6C, 0x0F, 0x9E, 0xFC, 0x31, 0xD3, 0x47, 0x2D, 0xDC, 0x1E, 0xC6, 0x09, 0x45, 0x1B,
29+
0x31, 0xF5, 0xC0, 0x24, 0xE1, 0x74, 0x93, 0x75, 0xA2, 0x49, 0xC0, 0x61, 0xA9, 0xD7, 0xF5, 0x7F,
30+
0x21, 0x81, 0x12, 0x90, 0x24, 0x61, 0x8C, 0x30, 0xD6, 0x24, 0x49, 0xA0, 0x50, 0x6A, 0x02, 0x04,
31+
0x0A, 0x43, 0x4D, 0x16, 0x97, 0x4F, 0xF8, 0x26, 0x0C, 0xE5, 0x50, 0x25, 0x10, 0x97, 0x2F, 0x48,
32+
0x0C, 0x0C, 0x11, 0x08, 0xB9, 0x1C, 0xA1, 0x5E, 0x78, 0x88, 0x1A, 0x2D, 0x06, 0xAC, 0x45, 0x8B,
33+
0xB5, 0xE4, 0xC6, 0xCA, 0x34, 0x6B, 0x96, 0xD4, 0x1A, 0x6E, 0x9C, 0x52, 0x9F, 0x5E, 0xC3, 0xB4,
34+
0xD8, 0x29, 0x2A, 0x9A, 0xF4, 0xE9, 0x37, 0xDA, 0x44, 0xB9, 0x3E, 0xCD, 0x5A, 0x84, 0xDC, 0x24,
35+
0xB5, 0x5A, 0x74, 0x6B, 0x31, 0x2C, 0x2B, 0x9C, 0xA0, 0x51, 0x87, 0xA5, 0x0F, 0x6E, 0xCE, 0x8D,
36+
0xD4, 0xAB, 0x1B, 0x42, 0xA5, 0x66, 0x8A, 0xE3, 0xE5, 0x4A, 0x23, 0xE2, 0xA1, 0xE6, 0x3C, 0x9B,
37+
0x36, 0x6B, 0x35, 0x54, 0x9E, 0xC4, 0x6B, 0xD4, 0x10, 0x9B, 0xE3, 0x2C, 0xB0, 0xCE, 0xFF, 0x2F,
38+
0xFC, 0xD3, 0xEB, 0x3E, 0x24, 0x35, 0x19, 0x80, 0x68, 0x01, 0x00, 0xB8, 0x8D, 0xE9, 0x7F, 0x25,
39+
0x81, 0x04, 0x04, 0x00, 0x86, 0x9B, 0x84, 0x0C, 0x19, 0x06, 0x50, 0xE0, 0xBA, 0x8E, 0xC0, 0x80,
40+
0xDC, 0x71, 0xA0, 0x43, 0x8B, 0x4C, 0x6E, 0x81, 0x63, 0xD2, 0x43, 0xFF, 0x60, 0x7F, 0x98, 0xBF,
41+
0xCF, 0x5F, 0x31, 0xE8, 0x56, 0x61, 0xBA, 0x63, 0x98, 0x95, 0xDB, 0xAC, 0x7E, 0xB2, 0x57, 0xB7,
42+
0xA1, 0xDF, 0xA1, 0x9F, 0xA1, 0xEF, 0x21, 0xF9, 0xF2, 0xEA, 0x3E, 0x04, 0x62, 0x96, 0xD8, 0xD7,
43+
0xAD, 0x6F, 0xC0, 0x74, 0x2C, 0x40, 0xE0, 0xD8, 0xBB, 0xBA, 0x82, 0x13, 0xC0, 0x55, 0xA0, 0xE4,
44+
0x0F, 0x7A, 0xA9, 0x19, 0xCB, 0x1F, 0x4C, 0xCD, 0x38, 0xFE, 0x30, 0x6A, 0xC6, 0xF3, 0xF7, 0xA9,
45+
0x66, 0x02, 0x83, 0x96, 0x9A, 0x89, 0x0C, 0xBA, 0x3F, 0x2A, 0x26, 0x69, 0x8D, 0xD5, 0x40, 0x54,
46+
0x49, 0x60, 0x32, 0xD8, 0x0F, 0xCC, 0xC4, 0x1B, 0xF0, 0x05, 0x80, 0x7A, 0x40, 0x00, 0xCE, 0x90,
47+
0x64, 0x6C, 0xC4, 0x15, 0x97, 0x79, 0x4B, 0x43, 0x5E, 0xDF, 0x94, 0xD7, 0xD5, 0xD6, 0xD6, 0x17,
48+
0x41, 0xB9, 0x53, 0x85, 0x22, 0x06, 0x54, 0x39, 0x46, 0xE5, 0x54, 0x56, 0xA4, 0x43, 0xCF, 0x22,
49+
0xDD, 0x9E, 0xE5, 0xE2, 0xE9, 0x2A, 0x65, 0x77, 0x36, 0x65, 0x9F, 0x69, 0x2A, 0x82, 0x05, 0xE7,
50+
0xA2, 0xF0, 0xAD, 0xB1, 0x7A, 0xD5, 0x77, 0x19, 0x39, 0x65, 0x44, 0xD9, 0xD0, 0xA8, 0x3C, 0xB5,
51+
0x9B, 0x94, 0xC9, 0x9D, 0x6A, 0x72, 0xEB, 0x84, 0x6B, 0x57, 0x2E, 0xB5, 0xB6, 0x25, 0x98, 0x46,
52+
0x65, 0x52, 0x65, 0xC2, 0xFE, 0x4E, 0xA3, 0xE8, 0x67, 0x80, 0x2A, 0xEF, 0x45, 0x0D, 0xB3, 0xB9,
53+
0x78, 0x6F, 0x90, 0x98, 0xF4, 0xDF, 0xDD, 0xDA, 0xB4, 0x92, 0xDA, 0xB6, 0x8A, 0xC7, 0x43, 0x71,
54+
0xCD, 0xB2, 0x87, 0x30, 0x29, 0x01, 0xE4, 0xAD, 0x58, 0x56, 0xCE, 0x97, 0xB8, 0xFA, 0x39, 0x3A,
55+
0x9C, 0x5F, 0xA7, 0xDA, 0x38, 0x14, 0x46, 0x98, 0xC6, 0x67, 0x8D, 0xCA, 0xDB, 0x70, 0x71, 0x66,
56+
0x96, 0xE9, 0xE2, 0x3D, 0x51, 0x4E, 0x69, 0x88, 0xB9, 0x7B, 0x32, 0x66, 0x99, 0x5F, 0xE5, 0x6F,
57+
0xB8, 0xEE, 0x5F, 0x2A, 0x03, 0x8F, 0x95, 0xEE, 0x01, 0x0B, 0x57, 0xF1, 0xD7, 0x15, 0x34, 0xDC,
58+
0xEB, 0x57, 0x00, 0x48, 0x6C, 0x98, 0x3E, 0x9E, 0xCC, 0x37, 0x7E, 0x6C, 0xB1, 0xF8, 0xDF, 0xB0,
59+
0x21, 0x81, 0xCF, 0xFF, 0x2E, 0xFF, 0x9D, 0x83, 0xEA, 0x49, 0xCA, 0x51, 0x2F, 0x81, 0x20, 0x01,
60+
0x34, 0x81, 0xCC, 0x3E, 0x12, 0xAD, 0x10, 0xC5, 0x4B, 0xB6, 0x96, 0x8F, 0x73, 0x5C, 0xD2, 0xC2,
61+
0x64, 0x1F, 0xD0, 0x03, 0x12, 0x42, 0x60, 0xB9, 0x03, 0xA0, 0xCE, 0x41, 0x1D, 0x91, 0x37, 0xE0,
62+
0x38, 0x88, 0x25, 0x61, 0xC0, 0x71, 0x49, 0xD2, 0xE4, 0xBA, 0x24, 0xB3, 0xD3, 0x7D, 0x3A, 0xAF,
63+
0x93, 0xD4, 0xE8, 0xF3, 0xFD, 0x52, 0x6A, 0x4D, 0xF4, 0xDF, 0x2A, 0x16, 0x5B, 0xC2, 0xA5, 0x90,
64+
0xC8, 0x7C, 0x88, 0x99, 0xA6, 0x9B, 0x61, 0x8E, 0xE1, 0xD6, 0xB1, 0x58, 0x24, 0x3A, 0xC1, 0xCE,
65+
0x70, 0x1B, 0x98, 0x38, 0x07, 0xC3, 0xAD, 0xA0, 0xD3, 0x21, 0x76, 0xF6, 0xFA, 0xBC, 0x8C, 0x47,
66+
0xF0, 0xF3, 0x02, 0x57, 0x08, 0x10, 0xEF, 0x60, 0x0B, 0x86, 0x4F, 0xF8, 0x47, 0x9C, 0xA1, 0xEB,
67+
0x34, 0x73, 0x2C, 0x26, 0xAF, 0x03, 0x24, 0x09, 0xE8, 0x18, 0xAE, 0xDB, 0x8A, 0xCF, 0xF7, 0x8B,
68+
0x2E, 0x89, 0xB0, 0x1B, 0xCF, 0x54, 0xE3, 0x0F, 0xB7, 0x70, 0x78, 0x35, 0x7B, 0x55, 0xFB, 0x7C,
69+
0x53, 0xCC, 0x34, 0xE5, 0x0C, 0xF1, 0xB9, 0xF6, 0x76, 0xC4, 0x3D, 0x4A, 0x65, 0x1C, 0x31, 0x43,
70+
0x71, 0xF6, 0x0C, 0x33, 0xE0, 0x02, 0x9D, 0xFD, 0xCE, 0xFC, 0x1D, 0x64, 0xAA, 0x9A, 0x99, 0x00
71+
};
72+
73+
unsigned int material_icons_subset_len = sizeof(material_icons_subset);
74+
#endif

‎examples/ws2812fx_segments_web/ws2812fx_segments_web.ino

+230-228
Large diffs are not rendered by default.

‎extras/WS2812FX change log.txt

+20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
WS2182FX Change Log
22

33

4+
v1.3.3 changes 4/15/2021
5+
------------------------
6+
7+
1) Added bits.h custom effect.
8+
9+
2) Added ws2812fx_matrix and ws2812fx_audio_reactive example sketches.
10+
11+
3) Made twinkleFOX one of the built-in effects, so it doesn't
12+
need to be included as a custom effect anymore. It's such a
13+
versatile, universal effect I thought it deserved a spot as
14+
a built-in effect.
15+
16+
4) Significant rewrite of the ws2812fx_segments_web example sketch.
17+
The web app now gets all of its resources from the ESP (instead
18+
of retrieving them from the Internet), and I've added some
19+
new features.
20+
21+
5) Some minor code cleanup (changed data type boolean to bool).
22+
23+
424
v1.3.2 changes 9/19/2020
525
------------------------
626

‎library.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"name": "Harm Aldick",
77
"url": "https://github.com/kitesurfer1404/WS2812FX"
88
},
9-
"version": "1.3.2",
9+
"version": "1.3.3",
1010
"downloadUrl": "https://github.com/kitesurfer1404/WS2812FX/archive/master.zip",
1111
"export": {
1212
"include": "WS2812FX-master"

‎library.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=WS2812FX
2-
version=1.3.2
2+
version=1.3.3
33
author=Harm Aldick
44
maintainer=Harm Aldick
55
sentence=WS2812 FX Library for Arduino and ESP microprocessors.

‎src/WS2812FX.cpp

+62-9
Original file line numberDiff line numberDiff line change
@@ -252,29 +252,29 @@ void WS2812FX::decreaseLength(uint16_t s) {
252252
if (s < seglen) setLength(seglen - s);
253253
}
254254

255-
boolean WS2812FX::isRunning() {
255+
bool WS2812FX::isRunning() {
256256
return _running;
257257
}
258258

259-
boolean WS2812FX::isTriggered() {
259+
bool WS2812FX::isTriggered() {
260260
return _triggered;
261261
}
262262

263-
boolean WS2812FX::isFrame() {
263+
bool WS2812FX::isFrame(void) {
264264
return isFrame(0);
265265
}
266266

267-
boolean WS2812FX::isFrame(uint8_t seg) {
267+
bool WS2812FX::isFrame(uint8_t seg) {
268268
uint8_t* ptr = (uint8_t*)memchr(_active_segments, seg, _active_segments_len);
269269
if(ptr == NULL) return false; // segment not active
270270
return (_segment_runtimes[ptr - _active_segments].aux_param2 & FRAME);
271271
}
272272

273-
boolean WS2812FX::isCycle() {
273+
bool WS2812FX::isCycle() {
274274
return isCycle(0);
275275
}
276276

277-
boolean WS2812FX::isCycle(uint8_t seg) {
277+
bool WS2812FX::isCycle(uint8_t seg) {
278278
uint8_t* ptr = (uint8_t*)memchr(_active_segments, seg, _active_segments_len);
279279
if(ptr == NULL) return false; // segment not active
280280
return (_segment_runtimes[ptr - _active_segments].aux_param2 & CYCLE);
@@ -457,7 +457,7 @@ void WS2812FX::swapActiveSegment(uint8_t oldSeg, uint8_t newSeg) {
457457
}
458458
}
459459

460-
boolean WS2812FX::isActiveSegment(uint8_t seg) {
460+
bool WS2812FX::isActiveSegment(uint8_t seg) {
461461
uint8_t* ptr = (uint8_t*)memchr(_active_segments, seg, _active_segments_len);
462462
if(ptr != NULL) return true;
463463
return false;
@@ -1479,7 +1479,7 @@ uint16_t WS2812FX::fireworks(uint32_t color) {
14791479
uint8_t *pixels = getPixels();
14801480
uint8_t bytesPerPixel = getNumBytesPerPixel(); // 3=RGB, 4=RGBW
14811481
uint16_t startPixel = _seg->start * bytesPerPixel + bytesPerPixel;
1482-
uint16_t stopPixel = _seg->stop * bytesPerPixel ;
1482+
uint16_t stopPixel = _seg->stop * bytesPerPixel;
14831483
for(uint16_t i=startPixel; i <stopPixel; i++) {
14841484
uint16_t tmpPixel = (pixels[i - bytesPerPixel] >> 2) +
14851485
pixels[i] +
@@ -1567,7 +1567,7 @@ uint16_t WS2812FX::mode_fire_flicker_intense(void) {
15671567

15681568

15691569
/*
1570-
* ICU mode
1570+
* ICU mode (moved to the custom effect folder)
15711571
*/
15721572
// uint16_t WS2812FX::mode_icu(void) {
15731573
// uint16_t dest = _seg_rt->counter_mode_step & 0xFFFF;
@@ -1603,6 +1603,59 @@ uint16_t WS2812FX::mode_fire_flicker_intense(void) {
16031603
// return (_seg->speed / _seg_len);
16041604
// }
16051605

1606+
// An adaptation of Mark Kriegsman's FastLED twinkeFOX effect
1607+
// https://gist.github.com/kriegsman/756ea6dcae8e30845b5a
1608+
uint16_t WS2812FX::mode_twinkleFOX(void) {
1609+
uint16_t mySeed = 0; // reset the random number generator seed
1610+
1611+
// Get and translate the segment's size option
1612+
uint8_t size = 1 << ((_seg->options >> 1) & 0x03); // 1,2,4,8
1613+
1614+
// Get the segment's colors array values
1615+
uint32_t color0 = _seg->colors[0];
1616+
uint32_t color1 = _seg->colors[1];
1617+
uint32_t color2 = _seg->colors[2];
1618+
uint32_t blendedColor;
1619+
1620+
for (uint16_t i = _seg->start; i <= _seg->stop; i+=size) {
1621+
// Use Mark Kriegsman's clever idea of using pseudo-random numbers to determine
1622+
// each LED's initial and increment blend values
1623+
mySeed = (mySeed * 2053) + 13849; // a random, but deterministic, number
1624+
uint16_t initValue = (mySeed + (mySeed >> 8)) & 0xff; // the LED's initial blend index (0-255)
1625+
mySeed = (mySeed * 2053) + 13849; // another random, but deterministic, number
1626+
uint16_t incrValue = (((mySeed + (mySeed >> 8)) & 0x07) + 1) * 2; // blend index increment (2,4,6,8,10,12,14,16)
1627+
1628+
// We're going to use a sine function to blend colors, instead of Mark's triangle
1629+
// function, simply because a sine lookup table is already built into the
1630+
// Adafruit_NeoPixel lib. Yes, I'm lazy.
1631+
// Use the counter_mode_call var as a clock "tick" counter and calc the blend index
1632+
uint8_t blendIndex = (initValue + (_seg_rt->counter_mode_call * incrValue)) & 0xff; // 0-255
1633+
// Index into the built-in Adafruit_NeoPixel sine table to lookup the blend amount
1634+
uint8_t blendAmt = Adafruit_NeoPixel::sine8(blendIndex); // 0-255
1635+
1636+
// If colors[0] is BLACK, blend random colors
1637+
if(color0 == BLACK) {
1638+
blendedColor = color_blend(color_wheel(initValue), color1, blendAmt);
1639+
// If colors[2] isn't BLACK, choose to blend colors[0]/colors[1] or colors[1]/colors[2]
1640+
// (which color pair to blend is picked randomly)
1641+
} else if((color2 != BLACK) && (initValue < 128) == 0) {
1642+
blendedColor = color_blend(color2, color1, blendAmt);
1643+
// Otherwise always blend colors[0]/colors[1]
1644+
} else {
1645+
blendedColor = color_blend(color0, color1, blendAmt);
1646+
}
1647+
1648+
// Assign the new color to the number of LEDs specified by the SIZE option
1649+
for(uint8_t j=0; j<size; j++) {
1650+
if((i + j) <= _seg->stop) {
1651+
setPixelColor(i + j, blendedColor);
1652+
}
1653+
}
1654+
}
1655+
setCycle();
1656+
return _seg->speed / 32;
1657+
}
1658+
16061659
/*
16071660
* Custom modes
16081661
*/

‎src/WS2812FX.h

+25-20
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,16 @@
177177
#define FX_MODE_HALLOWEEN 52
178178
#define FX_MODE_BICOLOR_CHASE 53
179179
#define FX_MODE_TRICOLOR_CHASE 54
180-
#define FX_MODE_CUSTOM 55 // keep this for backward compatiblity
181-
#define FX_MODE_CUSTOM_0 55 // custom modes need to go at the end
182-
#define FX_MODE_CUSTOM_1 56
183-
#define FX_MODE_CUSTOM_2 57
184-
#define FX_MODE_CUSTOM_3 58
185-
#define FX_MODE_CUSTOM_4 59
186-
#define FX_MODE_CUSTOM_5 60
187-
#define FX_MODE_CUSTOM_6 61
188-
#define FX_MODE_CUSTOM_7 62
180+
#define FX_MODE_TWINKLEFOX 55
181+
#define FX_MODE_CUSTOM 56 // keep this for backward compatiblity
182+
#define FX_MODE_CUSTOM_0 56 // custom modes need to go at the end
183+
#define FX_MODE_CUSTOM_1 57
184+
#define FX_MODE_CUSTOM_2 58
185+
#define FX_MODE_CUSTOM_3 59
186+
#define FX_MODE_CUSTOM_4 60
187+
#define FX_MODE_CUSTOM_5 61
188+
#define FX_MODE_CUSTOM_6 62
189+
#define FX_MODE_CUSTOM_7 63
189190

190191
// create GLOBAL names to allow WS2812FX to compile with sketches and other libs
191192
// that store strings in PROGMEM (get rid of the "section type conflict with __c"
@@ -245,14 +246,15 @@ const char name_51[] PROGMEM = "Circus Combustus";
245246
const char name_52[] PROGMEM = "Halloween";
246247
const char name_53[] PROGMEM = "Bicolor Chase";
247248
const char name_54[] PROGMEM = "Tricolor Chase";
248-
const char name_55[] PROGMEM = "Custom 0"; // custom modes need to go at the end
249-
const char name_56[] PROGMEM = "Custom 1";
250-
const char name_57[] PROGMEM = "Custom 2";
251-
const char name_58[] PROGMEM = "Custom 3";
252-
const char name_59[] PROGMEM = "Custom 4";
253-
const char name_60[] PROGMEM = "Custom 5";
254-
const char name_61[] PROGMEM = "Custom 6";
255-
const char name_62[] PROGMEM = "Custom 7";
249+
const char name_55[] PROGMEM = "TwinkleFOX";
250+
const char name_56[] PROGMEM = "Custom 0"; // custom modes need to go at the end
251+
const char name_57[] PROGMEM = "Custom 1";
252+
const char name_58[] PROGMEM = "Custom 2";
253+
const char name_59[] PROGMEM = "Custom 3";
254+
const char name_60[] PROGMEM = "Custom 4";
255+
const char name_61[] PROGMEM = "Custom 5";
256+
const char name_62[] PROGMEM = "Custom 6";
257+
const char name_63[] PROGMEM = "Custom 7";
256258

257259
static const __FlashStringHelper* _names[] = {
258260
FSH(name_0),
@@ -317,7 +319,8 @@ static const __FlashStringHelper* _names[] = {
317319
FSH(name_59),
318320
FSH(name_60),
319321
FSH(name_61),
320-
FSH(name_62)
322+
FSH(name_62),
323+
FSH(name_63)
321324
};
322325

323326
class WS2812FX : public Adafruit_NeoPixel {
@@ -422,7 +425,7 @@ class WS2812FX : public Adafruit_NeoPixel {
422425
setPixels(uint16_t, uint8_t*),
423426
show(void);
424427

425-
boolean
428+
bool
426429
isRunning(void),
427430
isTriggered(void),
428431
isFrame(void),
@@ -551,6 +554,7 @@ class WS2812FX : public Adafruit_NeoPixel {
551554
mode_circus_combustus(void),
552555
mode_bicolor_chase(void),
553556
mode_tricolor_chase(void),
557+
mode_twinkleFOX(void),
554558
mode_custom_0(void),
555559
mode_custom_1(void),
556560
mode_custom_2(void),
@@ -574,7 +578,7 @@ class WS2812FX : public Adafruit_NeoPixel {
574578
};
575579
void (*customShow)(void) = NULL;
576580

577-
boolean
581+
bool
578582
_running,
579583
_triggered;
580584

@@ -650,6 +654,7 @@ static WS2812FX::mode_ptr _modes[MODE_COUNT] = {
650654
&WS2812FX::mode_halloween,
651655
&WS2812FX::mode_bicolor_chase,
652656
&WS2812FX::mode_tricolor_chase,
657+
&WS2812FX::mode_twinkleFOX,
653658
&WS2812FX::mode_custom_0,
654659
&WS2812FX::mode_custom_1,
655660
&WS2812FX::mode_custom_2,

‎src/custom/Bits.h

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
Custom effect that shows a bit pattern in a rainbow of colors
3+
4+
5+
Keith Lord - 2021
6+
7+
LICENSE
8+
9+
The MIT License (MIT)
10+
11+
Copyright (c) 2021 Keith Lord
12+
13+
Permission is hereby granted, free of charge, to any person obtaining a copy
14+
of this software and associated documentation files (the "Software"), to deal
15+
in the Software without restriction, including without limitation the rights
16+
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
17+
copies of the Software, and to permit persons to whom the Software is
18+
furnished to do so, subject to the following conditions:
19+
20+
The above copyright notice and this permission notice shall be included in
21+
all copies or substantial portions of the Software.
22+
23+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29+
THE SOFTWARE.
30+
31+
CHANGELOG
32+
2021-03-14 initial version (pi day!)
33+
*/
34+
35+
#ifndef Bits_h
36+
#define Bits_h
37+
38+
#include <WS2812FX.h>
39+
40+
extern WS2812FX ws2812fx;
41+
42+
const char bitsData[] = "1110101111"; // pi=3.14
43+
44+
uint16_t bits(void) {
45+
WS2812FX::Segment* seg = ws2812fx.getSegment();
46+
WS2812FX::Segment_runtime* segrt = ws2812fx.getSegmentRuntime();
47+
int seglen = seg->stop - seg->start + 1;
48+
49+
int8_t colorIndex = segrt->aux_param++;
50+
uint8_t numBits = sizeof(bitsData) - 1;
51+
uint8_t ledsPerBit = seglen / (numBits * 2);
52+
//Serial.println(ledsPerBit);
53+
54+
uint32_t color = ws2812fx.color_wheel(segrt->aux_param++); // rainbow of colors
55+
uint16_t bitIndex = 0;
56+
for(uint16_t i=seg->start; i < numBits * ledsPerBit * 2; i += (ledsPerBit * 2)) {
57+
for(uint16_t j=0; j < ledsPerBit; j++) { // bit
58+
if(bitsData[bitIndex] == '1') {
59+
ws2812fx.setPixelColor(i + j, color);
60+
}else {
61+
ws2812fx.setPixelColor(i + j, BLACK);
62+
}
63+
}
64+
for(uint16_t j=0; j < ledsPerBit; j++) { // space
65+
ws2812fx.setPixelColor(i + ledsPerBit + j, BLACK);
66+
}
67+
bitIndex++;
68+
if(bitIndex >= numBits) bitIndex = 0;
69+
}
70+
71+
if(segrt->aux_param == 0) ws2812fx.setCycle();
72+
return seg->speed;
73+
}
74+
75+
#endif

‎src/custom/Matrix.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ struct Matrix {
6262
int8_t numPages;
6363
int8_t numRows;
6464
int8_t numCols;
65-
int32_t* colors;
65+
uint32_t* colors;
6666
};
6767
struct Matrix _matrix; // global variable, so this custom effect shouldn't be used in more then one segment
6868

‎src/custom/TwinkleFox.h

+6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@
3232
2019-11-25 initial version
3333
*/
3434

35+
/*
36+
Note: twinkleFOX is now one of the normal, built-in WS2812FX effects, so doesn't need to be
37+
included as a custom effect. I left it here just for historical reference. Eventually it'll
38+
be removed from the custom folder.
39+
*/
40+
3541
#ifndef Twinklefox_h
3642
#define Twinklefox_h
3743

0 commit comments

Comments
 (0)
Please sign in to comment.