Merge pull request #97 from Makuna/RotateAndShift

RotateAndShift
This commit is contained in:
Michael Miller
2016-04-06 17:53:39 -07:00
5 changed files with 288 additions and 3 deletions

View File

@@ -0,0 +1,96 @@
// NeoPixelFunLoop
// This example will move a trail of light around a series of pixels.
// A ring formation of pixels looks best.
// The trail will have a slowly fading tail.
//
// This will demonstrate the use of the RotateRight method.
//
#include <NeoPixelBus.h>
#include <NeoPixelAnimator.h>
const uint16_t PixelCount = 16; // make sure to set this to the number of pixels in your strip
const uint16_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266
const uint16_t AnimCount = 1; // we only need one
const uint16_t TailLength = 6; // length of the tail, must be shorter than PixelCount
const float MaxLightness = 0.4f; // max lightness at the head of the tail (0.5f is full bright)
NeoGamma<NeoGammaTableMethod> colorGamma; // for any fade animations, best to correct gamma
NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);
//NeoPixelBus<NeoGrbwFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);
NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object
void SetRandomSeed()
{
uint32_t seed;
// random works best with a seed that can use 31 bits
// analogRead on a unconnected pin tends toward less than four bits
seed = analogRead(0);
delay(1);
for (int shifts = 3; shifts < 31; shifts += 3)
{
seed ^= analogRead(0) << shifts;
delay(1);
}
// Serial.println(seed);
randomSeed(seed);
}
void LoopAnimUpdate(const AnimationParam& param)
{
// wait for this animation to complete,
// we are using it as a timer of sorts
if (param.state == AnimationState_Completed)
{
// done, time to restart this position tracking animation/timer
animations.RestartAnimation(param.index);
// rotate the complete strip one pixel to the right on every update
strip.RotateRight(1);
}
}
void DrawTailPixels()
{
// using Hsl as it makes it easy to pick from similiar saturated colors
float hue = random(360) / 360.0f;
for (uint16_t index = 0; index < strip.PixelCount() && index <= TailLength; index++)
{
float lightness = index * MaxLightness / TailLength;
RgbColor color = HslColor(hue, 1.0f, lightness);
strip.SetPixelColor(index, colorGamma.Correct(color));
}
}
void setup()
{
strip.Begin();
strip.Show();
SetRandomSeed();
// Draw the tail that will be rotated through all the rest of the pixels
DrawTailPixels();
// we use the index 0 animation to time how often we rotate all the pixels
animations.StartAnimation(0, 66, LoopAnimUpdate);
}
void loop()
{
// this is all that is needed to keep it running
// and avoiding using delay() is always a good thing for
// any timing related routines
animations.UpdateAnimations();
strip.Show();
}

View File

@@ -13,9 +13,11 @@ HslColor KEYWORD1
HsbColor KEYWORD1 HsbColor KEYWORD1
HtmlColor KEYWORD1 HtmlColor KEYWORD1
NeoGrbFeature KEYWORD1 NeoGrbFeature KEYWORD1
NeoGrbwFeature KEYWORD1
NeoRgbwFeature KEYWORD1 NeoRgbwFeature KEYWORD1
NeoRgbFeature KEYWORD1 NeoRgbFeature KEYWORD1
NeoBrgFeature KEYWORD1 NeoBrgFeature KEYWORD1
NeoRbgFeature KEYWORD1
Neo800KbpsMethod KEYWORD1 Neo800KbpsMethod KEYWORD1
Neo400KbpsMethod KEYWORD1 Neo400KbpsMethod KEYWORD1
NeoAvr800KbpsMethod KEYWORD1 NeoAvr800KbpsMethod KEYWORD1
@@ -66,6 +68,10 @@ Begin KEYWORD2
Show KEYWORD2 Show KEYWORD2
CanShow KEYWORD2 CanShow KEYWORD2
ClearTo KEYWORD2 ClearTo KEYWORD2
RotateLeft KEYWORD2
ShiftLeft KEYWORD2
RotateRight KEYWORD2
ShiftRight KEYWORD2
IsDirty KEYWORD2 IsDirty KEYWORD2
Dirty KEYWORD2 Dirty KEYWORD2
ResetDirty KEYWORD2 ResetDirty KEYWORD2

View File

@@ -1,5 +1,5 @@
name=NeoPixelBus by Makuna name=NeoPixelBus by Makuna
version=2.0.8 version=2.0.9
author=Michael C. Miller (makuna@live.com) author=Michael C. Miller (makuna@live.com)
maintainer=Michael C. Miller (makuna@live.com) maintainer=Michael C. Miller (makuna@live.com)
sentence=A library that makes controlling NeoPixels (WS2811, WS2812 & SK6812) easy. sentence=A library that makes controlling NeoPixels (WS2811, WS2812 & SK6812) easy.

View File

@@ -160,14 +160,150 @@ public:
void ClearTo(typename T_COLOR_FEATURE::ColorObject color) void ClearTo(typename T_COLOR_FEATURE::ColorObject color)
{ {
uint8_t temp[T_COLOR_FEATURE::PixelSize];
T_COLOR_FEATURE::applyPixelColor(temp, 0, color);
uint8_t* pixels = _method.getPixels(); uint8_t* pixels = _method.getPixels();
for (uint16_t n = 0; n < _countPixels; n++) uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, 0);
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(pixels, _countPixels);
uint8_t* pFront = temp;
while (pFirst < pLast)
{ {
T_COLOR_FEATURE::applyPixelColor(pixels, n, color); T_COLOR_FEATURE::copyIncPixel(pFirst, pFront);
} }
Dirty(); Dirty();
}; };
void RotateLeft(uint16_t rotationCount, uint16_t first = 0, uint16_t last = 0xffff)
{
if (last >= _countPixels)
{
last = _countPixels - 1;
}
if (first < _countPixels &&
last < _countPixels &&
first < last &&
(last - first) >= rotationCount)
{
// store in temp
uint8_t temp[rotationCount * T_COLOR_FEATURE::PixelSize];
uint8_t* pixels = _method.getPixels();
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(temp, 0);
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(temp, rotationCount - 1);
uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, first);
while (pFirst <= pLast)
{
T_COLOR_FEATURE::moveIncPixel(pFirst, pFront);
}
// shift data
ShiftLeft(rotationCount, first, last);
// move temp back
pFirst = T_COLOR_FEATURE::getPixelAddress(temp, 0);
pFront = T_COLOR_FEATURE::getPixelAddress(pixels, last - (rotationCount - 1));
while (pFirst <= pLast)
{
T_COLOR_FEATURE::moveIncPixel(pFront, pFirst);
}
Dirty();
}
}
void ShiftLeft(uint16_t shiftCount, uint16_t first = 0, uint16_t last = 0xffff)
{
if (last >= _countPixels)
{
last = _countPixels - 1;
}
if (first < _countPixels &&
last < _countPixels &&
first < last &&
(last - first) >= shiftCount)
{
uint8_t* pixels = _method.getPixels();
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, first);
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(pixels, last);
uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, first + shiftCount);
while (pFront <= pLast)
{
T_COLOR_FEATURE::moveIncPixel(pFirst, pFront);
}
Dirty();
}
}
void RotateRight(uint16_t rotationCount, uint16_t first = 0, uint16_t last = 0xffff)
{
if (last >= _countPixels)
{
last = _countPixels - 1;
}
if (first < _countPixels &&
last < _countPixels &&
first < last &&
(last - first) >= rotationCount)
{
// store in temp
uint8_t temp[rotationCount * T_COLOR_FEATURE::PixelSize];
uint8_t* pixels = _method.getPixels();
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(temp, 0);
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(temp, rotationCount - 1);
uint8_t* pBack = T_COLOR_FEATURE::getPixelAddress(pixels, last);
while (pLast >= pFirst)
{
T_COLOR_FEATURE::moveDecPixel(pLast, pBack);
}
// shift data
ShiftRight(rotationCount, first, last);
// move temp back
pLast = T_COLOR_FEATURE::getPixelAddress(temp, rotationCount - 1);
pBack = T_COLOR_FEATURE::getPixelAddress(pixels, first + rotationCount - 1);
while (pLast >= pFirst)
{
T_COLOR_FEATURE::moveDecPixel(pBack, pLast);
}
Dirty();
}
}
void ShiftRight(uint16_t shiftCount, uint16_t first = 0, uint16_t last = 0xffff)
{
if (last >= _countPixels)
{
last = _countPixels - 1;
}
if (first < _countPixels &&
last < _countPixels &&
first < last &&
(last - first) >= shiftCount)
{
uint8_t* pixels = _method.getPixels();
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, first);
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(pixels, last);
uint8_t* pBack = T_COLOR_FEATURE::getPixelAddress(pixels, last - shiftCount);
while (pBack >= pFirst)
{
T_COLOR_FEATURE::moveDecPixel(pLast, pBack);
}
Dirty();
}
}
private: private:
const uint16_t _countPixels; // Number of RGB LEDs in strip const uint16_t _countPixels; // Number of RGB LEDs in strip

View File

@@ -36,6 +36,27 @@ public:
return pPixels + indexPixel * PixelSize; return pPixels + indexPixel * PixelSize;
} }
static void copyIncPixel(uint8_t*& pPixelDest, uint8_t* pPixelSrc)
{
*pPixelDest++ = *pPixelSrc++;
*pPixelDest++ = *pPixelSrc++;
*pPixelDest++ = *pPixelSrc;
}
static void moveIncPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
{
*pPixelDest++ = *pPixelSrc++;
*pPixelDest++ = *pPixelSrc++;
*pPixelDest++ = *pPixelSrc++;
}
static void moveDecPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
{
*pPixelDest-- = *pPixelSrc--;
*pPixelDest-- = *pPixelSrc--;
*pPixelDest-- = *pPixelSrc--;
}
typedef RgbColor ColorObject; typedef RgbColor ColorObject;
}; };
@@ -49,6 +70,32 @@ public:
return pPixels + indexPixel * PixelSize; return pPixels + indexPixel * PixelSize;
} }
static void copyIncPixel(uint8_t*& pPixelDest, uint8_t* pPixelSrc)
{
uint32_t* pDest = (uint32_t*)pPixelDest;
uint32_t* pSrc = (uint32_t*)pPixelSrc;
*pDest++ = *pSrc;
pPixelDest = (uint8_t*)pDest;
}
static void moveIncPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
{
uint32_t* pDest = (uint32_t*)pPixelDest;
uint32_t* pSrc = (uint32_t*)pPixelSrc;
*pDest++ = *pSrc++;
pPixelDest = (uint8_t*)pDest;
pPixelSrc = (uint8_t*)pSrc;
}
static void moveDecPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
{
uint32_t* pDest = (uint32_t*)pPixelDest;
uint32_t* pSrc = (uint32_t*)pPixelSrc;
*pDest-- = *pSrc--;
pPixelDest = (uint8_t*)pDest;
pPixelSrc = (uint8_t*)pSrc;
}
typedef RgbwColor ColorObject; typedef RgbwColor ColorObject;
}; };