Moves a glow up and down a strip of WS2812 LEDs

Dependencies:   mbed wsDrive

Revision:
1:054df9ecd479
Parent:
0:35d68d1652e1
--- a/main.cpp	Wed Nov 05 16:50:38 2014 +0000
+++ b/main.cpp	Fri Nov 07 16:28:27 2014 +0000
@@ -2,20 +2,11 @@
 #include "wsDrive.h"
 
 // time period between each movement
-#define updatePeriodMS 25
+#define updatePeriodMS 15
 
 // number of LEDs in chain
 #define chainLen 144
 
-// length of the fade off behind the bright spot.
-// 1/8th of the chain length seems to look good (18 LEDs for a 144 chain)
-#define glowTail (chainLen/8)
-
-// background brightness left after the tail has passed.
-// final brightness = peak/backgroundRatio
-// set to be the same as the glow tail length for a smooth transition
-#define backgroundRatio glowTail
-
 // set the pulldown and then create the driver
 DigitalIn dummy(P0_21,PullDown);
 wsDrive ledDriver(P0_21,P0_22,P1_15);
@@ -27,122 +18,165 @@
 Timer updateRateTimer;
 
 // pixel storage buffer
-pixelInfo pixelData[chainLen];
+pixelInfo16 pixelData[chainLen];
+
+const uint8_t trailCount = 3;
+
+// info for each trail
+struct trailInfo {
+    float start;  // location of the trail from 0 to chainLen-1
+    int length;   // length of the trail
+    float speed;  // speed in moves at in LEDs per update
+    int backgroundRatio; // background glow level
+    pixelInfo colour;  // colour (and brightness) at the start of the chain
+    bool dir;       // direction of travel - true = increasing location
+};
+
+
+struct trailInfo lines[trailCount];
+
 
 void blankBuffer(pixelInfo *Ptr)
 {
     memset( (void *)Ptr, 0, chainLen*sizeof(pixelInfo) );
 }
 
+void blankBuffer(pixelInfo16 *Ptr)
+{
+    memset( (void *)Ptr, 0, chainLen*sizeof(pixelInfo16) );
+}
+
 void setPixel (pixelInfo *pixel, pixelInfo *colour, float level)
 {
+    pixel->R = (colour->R * level);
+    pixel->G = (colour->G * level);
+    pixel->B = (colour->B * level);
+}
 
-    pixel->R = (unsigned char) (colour->R * level);
-    pixel->G = (unsigned char) (colour->G * level);
-    pixel->B = (unsigned char) (colour->B * level);
+void addPixel (pixelInfo16 *pixel, pixelInfo *colour, float level)
+{
+    pixel->R = pixel->R + (int)(colour->R * level);
+    pixel->G = pixel->G + (int)(colour->G * level);
+    pixel->B = pixel->B + (int)(colour->B * level);
+}
+
+void subtractPixel (pixelInfo16 *pixel, pixelInfo *colour, float level)
+{
+    pixel->R = pixel->R - (int)(colour->R * level);
+    pixel->G = pixel->G - (int)(colour->G * level);
+    pixel->B = pixel->B - (int)(colour->B * level);
 }
 
 
-void setTrail (pixelInfo *colour, int peakPoint, bool increasing, int len)
+void setTrail(bool add, pixelInfo16* buffer, pixelInfo *colour, int peakPoint, bool increasing, int len)
 {
     int pixelToUpdate = peakPoint;
-    for (int pixel = 0; pixel <= len; pixel++) {
-        if (pixel == len) {
-            setPixel((pixelData+pixelToUpdate), colour, 1.0/backgroundRatio);
-            break;
-        }
-        setPixel((pixelData+pixelToUpdate), colour, 1.0 - (float)pixel/(float)len);
+    for (int pixel = 0; pixel < len; pixel++) {
+
+        if (add)
+            addPixel((buffer+pixelToUpdate), colour, 1.0 - (float)pixel/(float)len);
+        else
+            subtractPixel((buffer+pixelToUpdate), colour, 1.0 - (float)pixel/(float)len);
+
         increasing ? pixelToUpdate-- : pixelToUpdate++;
+
         if (pixelToUpdate == chainLen) {
             increasing = false;
-            pixelToUpdate = peakPoint - 1;
-            pixel = pixel*2;
+            pixelToUpdate = chainLen-2;
         }
         if (pixelToUpdate == -1) {
             increasing = true;
-            pixelToUpdate = peakPoint + 1;
-            pixel = pixel*2;
+            pixelToUpdate = 1;
         }
     }
 }
 
-
-void setColour(pixelInfo *colour)
+void removeTrail (pixelInfo16* buffer, pixelInfo *colour, int peakPoint, bool increasing, int len)
 {
-    static int cycleNumber = 0;
-
-    const int maxCycle = 40;
-    if (cycleNumber > maxCycle)
-        cycleNumber = 0;
+    setTrail (false, buffer, colour, peakPoint, increasing, len);
+}
 
-    switch (cycleNumber) {
-        case maxCycle:
-            cycleNumber = 0;
-        case 0:
-            colour->R = 0x80;
-            colour->G = 0x00;
-            colour->B = 0x00;
-            break;
-        case 10:
-            colour->R = 0x00;
-            colour->G = 0x70;
-            colour->B = 0x00;
-            break;
-        case 20:
-            colour->R = 0x00;
-            colour->G = 0x00;
-            colour->B = 0x80;
-            break;
-        case 30:
-            colour->R = 0x50;
-            colour->G = 0x40;
-            colour->B = 0x50;
-            break;
-        default:
-            break;
-    }
-    cycleNumber++;
+void addTrail (pixelInfo16* buffer, pixelInfo *colour, int peakPoint, bool increasing, int len)
+{
+    setTrail (true, buffer, colour, peakPoint, increasing, len);
 }
 
 
 int main ()
 {
     LEDs = 0;
-    // intialise variables
-    int peakPoint = 0;
-    bool increasing = true;
+
+
+    // set up the lights.
+    lines[0].start = 0;
+    lines[0].speed = 1.1;
+    lines[0].length = 20;
+    lines[0].backgroundRatio = 40;
+    lines[0].colour.R = 120;
+    lines[0].colour.G = 0;
+    lines[0].colour.B = 0;
+    lines[0].dir = true;
 
-    pixelInfo colour;
-    setColour(&colour);
+    lines[1].start = 0;
+    lines[1].speed = 2.0/3.0;
+    lines[1].length = 16;
+    lines[1].backgroundRatio = 40;
+    lines[1].colour.R = 0;
+    lines[1].colour.G = 0;
+    lines[1].colour.B = 120;
+    lines[1].dir = true;
 
+    lines[2].start = 143;
+    lines[2].speed = 1;
+    lines[2].length = 20;
+    lines[2].backgroundRatio = 40;
+    lines[2].colour.R = 0;
+    lines[2].colour.G = 120;
+    lines[2].colour.B = 0;
+    lines[2].dir = false;
+
+    // clear the buffer
     blankBuffer(pixelData);
 
+    // add the optional background
+    /*
+        for (int i = 0; i< chainLen; i++) {
+            for (int j = 0; j <trailCount; j++) {
+                addPixel((pixelData+i), &(lines[j].colour), 1.0/lines[j].backgroundRatio);
+            }
+        }
+    */
+
+// add the initial lines
+    for (int j = 0; j <trailCount; j++) {
+        addTrail (pixelData, &(lines[j].colour), lines[j].start, lines[j].dir, lines[j].length); // set the LED data
+    }
     // give the LED driver the buffer to use.
     ledDriver.setData(pixelData, chainLen);
 
     LEDs = 1;
 
-    setTrail (&colour, peakPoint, increasing, glowTail); // set the LED data
-
     updateRateTimer.start();
     while (true) {
         ledDriver.sendData(); // send the LED data
+
         LEDs = LEDs+1;
 
-        increasing ? peakPoint++ : peakPoint--; 
-        if (peakPoint == chainLen) {
-            increasing = false;
-            peakPoint = chainLen-2;
+        // subtract the current trail locations and then add the new locations.
+        for (int j = 0; j <trailCount; j++) {
+            removeTrail (pixelData, &(lines[j].colour), lines[j].start, lines[j].dir, lines[j].length); // set the LED data
+
+            lines[j].dir ? lines[j].start+=lines[j].speed : lines[j].start-=lines[j].speed;
+            if ((int)lines[j].start >= chainLen) {
+                lines[j].dir = false;
+                lines[j].start = chainLen-1 - lines[j].speed;
+            }
+            if ((int)lines[j].start <= -1) {
+                lines[j].dir = true;
+                lines[j].start = lines[j].speed;
+            }
+            addTrail (pixelData, &(lines[j].colour), lines[j].start, lines[j].dir, lines[j].length); // set the LED data
         }
-        if (peakPoint == -1) {
-            setColour(&colour);
-            increasing = true;
-            peakPoint = 1;
-        }
-        
-        // update to the next trail ready for the next update.
-        setTrail (&colour, peakPoint, increasing, glowTail); // set the LED data
-
         // wait for the next update time.
         while (updateRateTimer.read_ms() < updatePeriodMS) {
         }