Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FastLED/FastLED.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Guyer <sam.guyer@gmail.com>2018-05-08 22:10:15 +0300
committerDaniel Garcia <danielgarcia@gmail.com>2018-05-08 22:10:15 +0300
commitd41619400bbe77fe14dd1ccdca7521b152f460ef (patch)
tree529c91fec5858b46b528ee27765d1d006e8ba298 /examples
parent6fd236684e31c7703dfba697e86b2b8e9028b75f (diff)
ESP32 support using the RMT peripheral device (#522)
* Support for ESP32 Credit to Rina Shkrabova for the first cut. * Clean up interrupt handling I think there was actually an error in the interrupt enabling/disabling, but I also cleaned it up so that it is more clear how interrupts are handled. * Better interrupt handling * Added RMT version Not fully portable yet, though. The timing numbers are hard-wired for WS2812, and the RMT channel is also hard-wired. * Fixed the timing Timing is now computed from T1, T2, amd T3 instead of being hard-wired. * Better buffer management The RMT signal is sent in 10-pixel chunks, using double-buffering to hide the latency when possible. Also: assign RMT channels sequentially. * Total rewrite using Martin's code * Better comments * Fixed the timing calculation We were not doing the conversion from ESP32 cycles to RMT cycles correctly. Now it all works! * Added Martin's changes * Removed confusing comments * Added my name! * Fixed ESP32 compile problem On ESP platforms the dev kit provides the function __cxa_pure_virtual, so there is no need to define it. * honor WAIT_TIME for chipsets that need it (for example TM1829) * Better interrupt handling Suggested by @h3ndrik : allocated the interrupt once at the initialization and then just turn it on and off. This is the strategy that the ESP32 core uses also. * Major refactoring Two major changes to the RMT driver. First, I realized that we can have only one interrupt handler attached to the RMT peripheral, so it needs to be able to handle all of the attached strips. To accomplish this, I store each ClocklessController in an array indexed by its RMT channel. The interrupt handler can then take the channel that triggered it and index into the array to get the right controller. The second major change is that I replaced all of the explicit bit twiddling of the RMT configurartion with calls to the proper functions in ESP32 core. That should make the code more stable if the core changes. * Fixed the interrupt dispatch Since the interrupt handler is global for all channels, we need to store not just the controller, but also the buffer refill function for each strip. * Added a demo This version of DemoReel100 spins off a separate task on core 0 that just performs the FastLED.show() operations. Regular code running on core 1 (the default for Arduino) signals this task to request a show(). * Avoid unnecessary timeouts Replaced a 500ms delay in the show task with MAX_DELAY. There's really no point in timing out (and crashing the program) just because the application hasn't called show. * Parallel output Reworked the code again in order to support parallel output, which is now the default mode. You can also now ask it to use the built-in RMT driver if you have other parts of your code that need the RMT peripheral. Two #defines control choices -- put either or both of these before including FastLED.h: #define FASTLED_RMT_CORE_DRIVER Uses the ESP core RMT driver. To do this, though, it allocates a big buffer to hold all of the pixel bits, so there is a memory and compute cost. #define FASTLED_RMT_SERIAL_OUTPUT Force serial output of each strip. * Documentation Describing the implementation and the compile-time switches * Removing files that should not be there * Fixed synchronization The previous checkin had bugs in the syncronization that caused problems in parallel mode when strips are different lengths. * Fixed a stupid bug Made the code bullet-proof in a few ways, but most importantly fixed a terrible integer underflow bug in the code that fills the RMT buffer. * Another major overhaul The big change in this version is the ability to support more than 8 controllers. Instead of assigning RMT channels to controllers in a fixed mapping, channels are assigned on the fly, allowing the driver to reuse channels as they become available. * Oops Didn't mean to check these in. * Fixed built-in driver mode Fixed the code so that it works with the built-in RMT driver. There's nothing special to do to enable it -- just #define FASTLED_RMT_BUILTIN_DRIVER true * Cleanup Fixing some documentation and configuration stuff
Diffstat (limited to 'examples')
-rw-r--r--examples/DemoReelESP32/DemoReelESP32.ino181
1 files changed, 181 insertions, 0 deletions
diff --git a/examples/DemoReelESP32/DemoReelESP32.ino b/examples/DemoReelESP32/DemoReelESP32.ino
new file mode 100644
index 00000000..3a32d4c4
--- /dev/null
+++ b/examples/DemoReelESP32/DemoReelESP32.ino
@@ -0,0 +1,181 @@
+#include "FastLED.h"
+
+FASTLED_USING_NAMESPACE
+
+// FastLED "100-lines-of-code" demo reel, showing just a few
+// of the kinds of animation patterns you can quickly and easily
+// compose using FastLED.
+//
+// This example also shows one easy way to define multiple
+// animations patterns and have them automatically rotate.
+//
+// -Mark Kriegsman, December 2014
+
+#if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000)
+#warning "Requires FastLED 3.1 or later; check github for latest code."
+#endif
+
+#define DATA_PIN 12
+//#define CLK_PIN 4
+#define LED_TYPE WS2811
+#define COLOR_ORDER GRB
+#define NUM_LEDS 27
+CRGB leds[NUM_LEDS];
+
+#define BRIGHTNESS 60
+#define FRAMES_PER_SECOND 120
+
+// -- The core to run FastLED.show()
+#define FASTLED_SHOW_CORE 0
+
+// -- Task handles for use in the notifications
+static TaskHandle_t FastLEDshowTaskHandle = 0;
+static TaskHandle_t userTaskHandle = 0;
+
+/** show() for ESP32
+ * Call this function instead of FastLED.show(). It signals core 0 to issue a show,
+ * then waits for a notification that it is done.
+ */
+void FastLEDshowESP32()
+{
+ if (userTaskHandle == 0) {
+ // -- Store the handle of the current task, so that the show task can
+ // notify it when it's done
+ userTaskHandle = xTaskGetCurrentTaskHandle();
+
+ // -- Trigger the show task
+ xTaskNotifyGive(FastLEDshowTaskHandle);
+
+ // -- Wait to be notified that it's done
+ const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 200 );
+ ulTaskNotifyTake(pdTRUE, xMaxBlockTime);
+ userTaskHandle = 0;
+ }
+}
+
+/** show Task
+ * This function runs on core 0 and just waits for requests to call FastLED.show()
+ */
+void FastLEDshowTask(void *pvParameters)
+{
+ // -- Run forever...
+ for(;;) {
+ // -- Wait for the trigger
+ ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
+
+ // -- Do the show (synchronously)
+ FastLED.show();
+
+ // -- Notify the calling task
+ xTaskNotifyGive(userTaskHandle);
+ }
+}
+
+void setup() {
+ delay(3000); // 3 second delay for recovery
+ Serial.begin(115200);
+
+ // tell FastLED about the LED strip configuration
+ FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
+ //FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
+
+ // set master brightness control
+ FastLED.setBrightness(BRIGHTNESS);
+
+ int core = xPortGetCoreID();
+ Serial.print("Main code running on core ");
+ Serial.println(core);
+
+ // -- Create the FastLED show task
+ xTaskCreatePinnedToCore(FastLEDshowTask, "FastLEDshowTask", 2048, NULL, 2, &FastLEDshowTaskHandle, FASTLED_SHOW_CORE);
+}
+
+
+// List of patterns to cycle through. Each is defined as a separate function below.
+typedef void (*SimplePatternList[])();
+SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm };
+
+uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
+uint8_t gHue = 0; // rotating "base color" used by many of the patterns
+
+void loop()
+{
+ // Call the current pattern function once, updating the 'leds' array
+ gPatterns[gCurrentPatternNumber]();
+
+ // send the 'leds' array out to the actual LED strip
+ FastLEDshowESP32();
+ // FastLED.show();
+ // insert a delay to keep the framerate modest
+ FastLED.delay(1000/FRAMES_PER_SECOND);
+
+ // do some periodic updates
+ EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
+ EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
+}
+
+#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
+
+void nextPattern()
+{
+ // add one to the current pattern number, and wrap around at the end
+ gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
+}
+
+void rainbow()
+{
+ // FastLED's built-in rainbow generator
+ fill_rainbow( leds, NUM_LEDS, gHue, 7);
+}
+
+void rainbowWithGlitter()
+{
+ // built-in FastLED rainbow, plus some random sparkly glitter
+ rainbow();
+ addGlitter(80);
+}
+
+void addGlitter( fract8 chanceOfGlitter)
+{
+ if( random8() < chanceOfGlitter) {
+ leds[ random16(NUM_LEDS) ] += CRGB::White;
+ }
+}
+
+void confetti()
+{
+ // random colored speckles that blink in and fade smoothly
+ fadeToBlackBy( leds, NUM_LEDS, 10);
+ int pos = random16(NUM_LEDS);
+ leds[pos] += CHSV( gHue + random8(64), 200, 255);
+}
+
+void sinelon()
+{
+ // a colored dot sweeping back and forth, with fading trails
+ fadeToBlackBy( leds, NUM_LEDS, 20);
+ int pos = beatsin16( 13, 0, NUM_LEDS-1 );
+ leds[pos] += CHSV( gHue, 255, 192);
+}
+
+void bpm()
+{
+ // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
+ uint8_t BeatsPerMinute = 62;
+ CRGBPalette16 palette = PartyColors_p;
+ uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
+ for( int i = 0; i < NUM_LEDS; i++) { //9948
+ leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
+ }
+}
+
+void juggle() {
+ // eight colored dots, weaving in and out of sync with each other
+ fadeToBlackBy( leds, NUM_LEDS, 20);
+ byte dothue = 0;
+ for( int i = 0; i < 8; i++) {
+ leds[beatsin16( i+7, 0, NUM_LEDS-1 )] |= CHSV(dothue, 200, 255);
+ dothue += 32;
+ }
+}
+