Skip to content

Commit

Permalink
Custom effects are now built-in for ESP and RP2040 (#316)
Browse files Browse the repository at this point in the history
* Only for ESP devices, converted 8 custom effects into nuilt-in effects

* converted two more custom effects to built-in effects, created segment_runtime external data source

* converted two more custom effects into built-in effects

* run the test suite, added RP2040 to support external data

* converted the last three custom effects into built-in effects

* added ws2812fx_extData example sketch and updated change log

* fixed rainbow_cycle effect

* tweaked the popcorn effect so it would work ok with a default number of kernels

* fixed the effects that use external data

* setup bits effect with default bit array

* tweaks to rainbow effects
  • Loading branch information
moose4lord authored Jul 24, 2022
1 parent 2b62056 commit 6a38dd4
Show file tree
Hide file tree
Showing 13 changed files with 1,107 additions and 59 deletions.
23 changes: 17 additions & 6 deletions examples/tester.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,35 @@
# simple test script that verifies all the WS2812FX example sketches.
# note: behind the scenes this script runs the Arduino IDE, so you will see
# the IDE's splash screen displayed during each individual test.
# also note: ths script takes a long time to run.
# also note: this script takes a long time to run. better to pip the output
# a file and go get a cup of coffee:
# ./tester.zsh > tester.txt

# add the Arduino application to $PATH
export PATH=$PATH:/Applications/Arduino.app/Contents/MacOS

# test that we can execute the Arduino command
#Arduino --version

# board aliases
# board aliases (fully qualified board name)
alias -g leonardo-board="arduino:avr:leonardo"
alias -g esp8266-board="esp8266:esp8266:nodemcuv2"
alias -g esp32-board="esp32:esp32:esp32doit-devkit-v1"
alias -g rp2040-board="arduino:mbed_rp2040:pico"

# port aliases
alias -g leonardo-port="/dev/cu.usbmodem14101"
alias -g leonardo-port="/dev/cu.usbmodem14101 (Arduino Leonardo)"
alias -g esp8266-port="/dev/cu.usbserial-0001"
alias -g esp32-port="/dev/cu.usbserial-0001"
alias -g rp2040-port="/dev/cu.usbmodem14101 (Raspberry Pi Pico)"

# example verify command:
# arduino --board leonardo-board --verify ws2812fx_segments/ws2812fx_segments.ino

# example upload command:
#arduino --board leonardo-board --port leonardo-port --upload ws2812fx_segments/ws2812fx_segments.ino

# create an list of basic example sketches that can be verified for all boards
# create a list of basic example sketches that can be verified for all boards
basic_sketches=(
'auto_mode_cycle/auto_mode_cycle.ino',
'external_trigger/external_trigger.ino',
Expand Down Expand Up @@ -65,13 +69,20 @@ for ((i = 1; i <= $#basic_sketches; i++)) {
arduino --board esp32-board --verify $basic_sketches[i] 2>/dev/null; echo "exit status" $?
}

# create an list of example sketches that use WiFi to be verified only on ESP boards
# run verify command for all sketches for the RP2040 board
for ((i = 1; i <= $#basic_sketches; i++)) {
echo "\nVerifing" $basic_sketches[i] for RP2040
arduino --board rp2040-board --verify $basic_sketches[i] 2>/dev/null; echo "exit status" $?
}

# create a list of example sketches that use WiFi to be verified only on ESP boards
wifi_sketches=(
'esp8266_webinterface/esp8266_webinterface.ino',
'ws2812fx_alexa/ws2812fx_alexa.ino',
'ws2812fx_patterns_web/ws2812fx_patterns_web.ino',
'ws2812fx_segments_OTA/ws2812fx_segments_OTA.ino',
'ws2812fx_segments_web/ws2812fx_segments_web.ino'
'ws2812fx_segments_web/ws2812fx_segments_web.ino',
'ws2812fx_extData/ws2812fx_extData.ino'
)

# run verify command for all sketches for the ESP8266 board
Expand Down
388 changes: 388 additions & 0 deletions examples/tester_Jul2022.txt

Large diffs are not rendered by default.

File renamed without changes.
72 changes: 72 additions & 0 deletions examples/ws2812fx_extData/ws2812fx_extData.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
WS2812FX v1.41 introduced the ability to inject external data into some
of the more advanced effects. This sketch demontrates how to do that.
Note: by default, the "more advanced effects" are only setup to compile
for microprocessors that have plentiful memory (like ESPs or RP2040s).
The compile will fail if targetting an old, wimpy Arduino.
Keith Lord - 2022
LICENSE
The MIT License (MIT)
Copyright (c) 2018 Keith Lord
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
CHANGELOG
2022-07-12 initial version
*/

#include <WS2812FX.h>

#define LED_PIN 12 // digital pin used to drive the LED strip
#define LED_COUNT 30 // number of LEDs on the strip

WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

// the oscillator effect produces two "oscillators" by default. We're going
// to inject our own Oscillator struct array that creates three oscillators.
Oscillator oscillators[] = { // 3 oscillators
{LED_COUNT/4, 0, 1}, // size, pos, speed
{LED_COUNT/4, LED_COUNT / 2, 2},
{LED_COUNT/4, LED_COUNT - 1, -2}
};
uint16_t numOsc = sizeof(oscillators) / sizeof(oscillators[0]);

void setup() {
ws2812fx.init();
ws2812fx.setBrightness(64);

// Here's where we'll instruct segment 0 to use our custom oscillator array
// by setting an external data source. Note the setExtDataSrc() function expects
// a (uint8_t*) pointer, so cast accordingly.
// parameters: seg, pointer to external data array, number of data array elemenst
ws2812fx.setExtDataSrc(0, (uint8_t*)&oscillators, numOsc);

// parameters: seg, start, stop, mode, colors, speed
ws2812fx.setSegment(0, 0, LED_COUNT-1, FX_MODE_OSCILLATOR, COLORS(RED, GREEN, BLUE), 1000);

ws2812fx.start();
}

void loop() {
ws2812fx.service();
}
55 changes: 55 additions & 0 deletions extras/WS2812FX change log.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,61 @@
WS2182FX Change Log


v1.4.1 changes 07/18/2022
-------------------------

1) Since ESP and Arduino microprocessors now have separate header
files (see v1.4.0 change log notes), the 15 custom effects were
added as built-in effects for ESP (and RP2040) devices. The
mechanism to add custom effects is still available for Arduino
projects (see the ws2812fx_custom_effect2 example sketch), but
with limited memory, you'll need to pick and choose the custom
effects that you want included in Arduino projects.
The following effects are now built-in for ESP and RP2040 devices:
Block Dissolve
ICU
Dual Larson
Running Random2
Filler Up
Rainbow Larson
Rainbow Fireworks
Trifade
VU Meter
Heartbeat
Bits
Multi Comet
Flipbook (same as the matrix custom effect)
Popcorn
Oscillator

2) The ability to inject external data into some of the "new"
built-in effects was added. This allows potentially very large
arrays or data structs to be used by effects and control how
they behave. The new ws2812fx_extData example sketch demonstrates
how this can be done. Probably not something for a novice
developer, but can be a very powerful feature if you know what
you're doing.

3) renamed the "random_wipe_bright" effect to "running_random2", since
it's really just a variant of the running_random effect.

4) added getRawPixelColor() and setRawPixelColor() utility functions
to get/set pixel data without regard to the Adafruit_NeoPixel
global brightness rigmarole.

5) Modified the rainbow_cycle effect so that it would work well with
very short segments of LEDs. The timing was slowed down a bit as
well, so you may need to adjust the speed parameter if you're
using that effect.

6) Tweaked the blink_rainbow and strobe_rainbow effects, so the
colors would change more quickly.

7) Modified the tester.zsh automated testing script to include tests
for RP2040 processors. examples/tester_Jul2022.txt contains the
latest test results.


v1.4.0 changes 03/23/2022
-------------------------

Expand Down
15 changes: 15 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,21 @@ FX_MODE_BICOLOR_CHASE KEYWORD2
FX_MODE_TRICOLOR_CHASE KEYWORD2
FX_MODE_TWINKLEFOX KEYWORD2
FX_MODE_RAIN KEYWORD2
FX_MODE_BLOCK_DISSOLVE KEYWORD2
FX_MODE_ICU KEYWORD2
FX_MODE_DUAL_LARSON KEYWORD2
FX_MODE_RUNNING_RANDOM2 KEYWORD2
FX_MODE_FILLER_UP KEYWORD2
FX_MODE_RAINBOW_LARSON KEYWORD2
FX_MODE_RAINBOW_FIREWORKS KEYWORD2
FX_MODE_TRIFADE KEYWORD2
FX_MODE_VU_METER KEYWORD2
FX_MODE_HEARTBEAT KEYWORD2
FX_MODE_BITS KEYWORD2
FX_MODE_MULTI_COMET KEYWORD2
FX_MODE_FLIPBOOK KEYWORD2
FX_MODE_POPCORN KEYWORD2
FX_MODE_OSCILLATOR KEYWORD2
FX_MODE_CUSTOM KEYWORD2
FX_MODE_CUSTOM_0 KEYWORD2
FX_MODE_CUSTOM_1 KEYWORD2
Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"name": "Harm Aldick",
"url": "https://github.com/kitesurfer1404/WS2812FX"
},
"version": "1.4.0",
"version": "1.4.1",
"frameworks": "arduino",
"platforms": "*",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=WS2812FX
version=1.4.0
version=1.4.1
author=Harm Aldick
maintainer=Harm Aldick
sentence=WS2812 FX Library for Arduino and ESP microprocessors.
Expand Down
46 changes: 44 additions & 2 deletions src/WS2812FX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,32 @@ void WS2812FX::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_
}
}

// custom setPixelColor() function that bypasses the Adafruit_Neopixel global brightness rigmarole
void WS2812FX::setRawPixelColor(uint16_t n, uint32_t c) {
if (n < numLEDs) {
uint8_t *p = (wOffset == rOffset) ? &pixels[n * 3] : &pixels[n * 4];
uint8_t w = (uint8_t)(c >> 24), r = (uint8_t)(c >> 16), g = (uint8_t)(c >> 8), b = (uint8_t)c;

p[wOffset] = w;
p[rOffset] = r;
p[gOffset] = g;
p[bOffset] = b;
}
}

// custom getPixelColor() function that bypasses the Adafruit_Neopixel global brightness rigmarole
uint32_t WS2812FX::getRawPixelColor(uint16_t n) {
if (n >= numLEDs) return 0; // Out of bounds, return no color.

if(wOffset == rOffset) { // RGB
uint8_t *p = &pixels[n * 3];
return ((uint32_t)p[rOffset] << 16) | ((uint32_t)p[gOffset] << 8) | (uint32_t)p[bOffset];
} else { // RGBW
uint8_t *p = &pixels[n * 4];
return ((uint32_t)p[wOffset] << 24) | ((uint32_t)p[rOffset] << 16) | ((uint32_t)p[gOffset] << 8) | (uint32_t)p[bOffset];
}
}

void WS2812FX::copyPixels(uint16_t dest, uint16_t src, uint16_t count) {
uint8_t *pixels = getPixels();
uint8_t bytesPerPixel = getNumBytesPerPixel(); // 3=RGB, 4=RGBW
Expand Down Expand Up @@ -511,13 +537,21 @@ void WS2812FX::resetSegments() {
}

void WS2812FX::resetSegmentRuntimes() {
memset(_segment_runtimes, 0, _active_segments_len * sizeof(Segment_runtime));
for(uint8_t i=0; i<_segments_len; i++) {
resetSegmentRuntime(i);
};
}

void WS2812FX::resetSegmentRuntime(uint8_t seg) {
uint8_t* ptr = (uint8_t*)memchr(_active_segments, seg, _active_segments_len);
if(ptr == NULL) return; // segment not active
memset(&_segment_runtimes[ptr - _active_segments], 0, sizeof(Segment_runtime));
_segment_runtimes[seg].next_time = 0;
_segment_runtimes[seg].counter_mode_step = 0;
_segment_runtimes[seg].counter_mode_call = 0;
_segment_runtimes[seg].aux_param = 0;
_segment_runtimes[seg].aux_param2 = 0;
_segment_runtimes[seg].aux_param3 = 0;
// don't reset any external data source
}

/*
Expand Down Expand Up @@ -651,3 +685,11 @@ uint8_t WS2812FX::setCustomMode(uint8_t index, const __FlashStringHelper* name,
void WS2812FX::setCustomShow(void (*p)()) {
customShow = p;
}

/*
* set a segment runtime's external data source
*/
void WS2812FX::setExtDataSrc(uint8_t seg, uint8_t *src, uint8_t cnt) {
_segment_runtimes[seg].extDataSrc = src;
_segment_runtimes[seg].extDataCnt = cnt;
}
Loading

0 comments on commit 6a38dd4

Please sign in to comment.