Skip to content

Commit

Permalink
Merge pull request #97 from Makuna/RotateAndShift
Browse files Browse the repository at this point in the history
RotateAndShift
  • Loading branch information
Makuna committed Apr 7, 2016
2 parents 44b0943 + 6e860c9 commit aca0fe3
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 3 deletions.
96 changes: 96 additions & 0 deletions examples/NeoPixelRotateLoop/NeoPixelRotateLoop.ino
Original file line number Diff line number Diff line change
@@ -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();
}


6 changes: 6 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ HslColor KEYWORD1
HsbColor KEYWORD1
HtmlColor KEYWORD1
NeoGrbFeature KEYWORD1
NeoGrbwFeature KEYWORD1
NeoRgbwFeature KEYWORD1
NeoRgbFeature KEYWORD1
NeoBrgFeature KEYWORD1
NeoRbgFeature KEYWORD1
Neo800KbpsMethod KEYWORD1
Neo400KbpsMethod KEYWORD1
NeoAvr800KbpsMethod KEYWORD1
Expand Down Expand Up @@ -66,6 +68,10 @@ Begin KEYWORD2
Show KEYWORD2
CanShow KEYWORD2
ClearTo KEYWORD2
RotateLeft KEYWORD2
ShiftLeft KEYWORD2
RotateRight KEYWORD2
ShiftRight KEYWORD2
IsDirty KEYWORD2
Dirty KEYWORD2
ResetDirty KEYWORD2
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=NeoPixelBus by Makuna
version=2.0.8
version=2.0.9
author=Michael C. Miller (makuna@live.com)
maintainer=Michael C. Miller (makuna@live.com)
sentence=A library that makes controlling NeoPixels (WS2811, WS2812 & SK6812) easy.
Expand Down
140 changes: 138 additions & 2 deletions src/NeoPixelBus.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,150 @@ template<typename T_COLOR_FEATURE, typename T_METHOD> class NeoPixelBus

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();
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();
};

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:
const uint16_t _countPixels; // Number of RGB LEDs in strip

Expand Down
47 changes: 47 additions & 0 deletions src/internal/NeoColorFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,27 @@ class Neo3Elements
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;
};

Expand All @@ -49,6 +70,32 @@ class Neo4Elements
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;
};

Expand Down

0 comments on commit aca0fe3

Please sign in to comment.