Skip to content

Commit aca0fe3

Browse files
committed
Merge pull request #97 from Makuna/RotateAndShift
RotateAndShift
2 parents 44b0943 + 6e860c9 commit aca0fe3

5 files changed

Lines changed: 288 additions & 3 deletions

File tree

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// NeoPixelFunLoop
2+
// This example will move a trail of light around a series of pixels.
3+
// A ring formation of pixels looks best.
4+
// The trail will have a slowly fading tail.
5+
//
6+
// This will demonstrate the use of the RotateRight method.
7+
//
8+
9+
#include <NeoPixelBus.h>
10+
#include <NeoPixelAnimator.h>
11+
12+
13+
const uint16_t PixelCount = 16; // make sure to set this to the number of pixels in your strip
14+
const uint16_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266
15+
const uint16_t AnimCount = 1; // we only need one
16+
const uint16_t TailLength = 6; // length of the tail, must be shorter than PixelCount
17+
const float MaxLightness = 0.4f; // max lightness at the head of the tail (0.5f is full bright)
18+
19+
NeoGamma<NeoGammaTableMethod> colorGamma; // for any fade animations, best to correct gamma
20+
21+
NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);
22+
//NeoPixelBus<NeoGrbwFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);
23+
24+
NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object
25+
26+
void SetRandomSeed()
27+
{
28+
uint32_t seed;
29+
30+
// random works best with a seed that can use 31 bits
31+
// analogRead on a unconnected pin tends toward less than four bits
32+
seed = analogRead(0);
33+
delay(1);
34+
35+
for (int shifts = 3; shifts < 31; shifts += 3)
36+
{
37+
seed ^= analogRead(0) << shifts;
38+
delay(1);
39+
}
40+
41+
// Serial.println(seed);
42+
randomSeed(seed);
43+
}
44+
45+
void LoopAnimUpdate(const AnimationParam& param)
46+
{
47+
// wait for this animation to complete,
48+
// we are using it as a timer of sorts
49+
if (param.state == AnimationState_Completed)
50+
{
51+
// done, time to restart this position tracking animation/timer
52+
animations.RestartAnimation(param.index);
53+
54+
// rotate the complete strip one pixel to the right on every update
55+
strip.RotateRight(1);
56+
}
57+
}
58+
59+
void DrawTailPixels()
60+
{
61+
// using Hsl as it makes it easy to pick from similiar saturated colors
62+
float hue = random(360) / 360.0f;
63+
for (uint16_t index = 0; index < strip.PixelCount() && index <= TailLength; index++)
64+
{
65+
float lightness = index * MaxLightness / TailLength;
66+
RgbColor color = HslColor(hue, 1.0f, lightness);
67+
68+
strip.SetPixelColor(index, colorGamma.Correct(color));
69+
}
70+
}
71+
72+
void setup()
73+
{
74+
strip.Begin();
75+
strip.Show();
76+
77+
SetRandomSeed();
78+
79+
// Draw the tail that will be rotated through all the rest of the pixels
80+
DrawTailPixels();
81+
82+
// we use the index 0 animation to time how often we rotate all the pixels
83+
animations.StartAnimation(0, 66, LoopAnimUpdate);
84+
}
85+
86+
87+
void loop()
88+
{
89+
// this is all that is needed to keep it running
90+
// and avoiding using delay() is always a good thing for
91+
// any timing related routines
92+
animations.UpdateAnimations();
93+
strip.Show();
94+
}
95+
96+

keywords.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ HslColor KEYWORD1
1313
HsbColor KEYWORD1
1414
HtmlColor KEYWORD1
1515
NeoGrbFeature KEYWORD1
16+
NeoGrbwFeature KEYWORD1
1617
NeoRgbwFeature KEYWORD1
1718
NeoRgbFeature KEYWORD1
1819
NeoBrgFeature KEYWORD1
20+
NeoRbgFeature KEYWORD1
1921
Neo800KbpsMethod KEYWORD1
2022
Neo400KbpsMethod KEYWORD1
2123
NeoAvr800KbpsMethod KEYWORD1
@@ -66,6 +68,10 @@ Begin KEYWORD2
6668
Show KEYWORD2
6769
CanShow KEYWORD2
6870
ClearTo KEYWORD2
71+
RotateLeft KEYWORD2
72+
ShiftLeft KEYWORD2
73+
RotateRight KEYWORD2
74+
ShiftRight KEYWORD2
6975
IsDirty KEYWORD2
7076
Dirty KEYWORD2
7177
ResetDirty KEYWORD2

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=NeoPixelBus by Makuna
2-
version=2.0.8
2+
version=2.0.9
33
author=Michael C. Miller (makuna@live.com)
44
maintainer=Michael C. Miller (makuna@live.com)
55
sentence=A library that makes controlling NeoPixels (WS2811, WS2812 & SK6812) easy.

src/NeoPixelBus.h

Lines changed: 138 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,150 @@ template<typename T_COLOR_FEATURE, typename T_METHOD> class NeoPixelBus
160160

161161
void ClearTo(typename T_COLOR_FEATURE::ColorObject color)
162162
{
163+
uint8_t temp[T_COLOR_FEATURE::PixelSize];
164+
165+
T_COLOR_FEATURE::applyPixelColor(temp, 0, color);
166+
163167
uint8_t* pixels = _method.getPixels();
164-
for (uint16_t n = 0; n < _countPixels; n++)
168+
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, 0);
169+
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(pixels, _countPixels);
170+
uint8_t* pFront = temp;
171+
while (pFirst < pLast)
165172
{
166-
T_COLOR_FEATURE::applyPixelColor(pixels, n, color);
173+
T_COLOR_FEATURE::copyIncPixel(pFirst, pFront);
167174
}
175+
168176
Dirty();
169177
};
170178

179+
void RotateLeft(uint16_t rotationCount, uint16_t first = 0, uint16_t last = 0xffff)
180+
{
181+
if (last >= _countPixels)
182+
{
183+
last = _countPixels - 1;
184+
}
185+
186+
if (first < _countPixels &&
187+
last < _countPixels &&
188+
first < last &&
189+
(last - first) >= rotationCount)
190+
{
191+
192+
// store in temp
193+
uint8_t temp[rotationCount * T_COLOR_FEATURE::PixelSize];
194+
uint8_t* pixels = _method.getPixels();
195+
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(temp, 0);
196+
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(temp, rotationCount - 1);
197+
uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, first);
198+
while (pFirst <= pLast)
199+
{
200+
T_COLOR_FEATURE::moveIncPixel(pFirst, pFront);
201+
}
202+
203+
// shift data
204+
ShiftLeft(rotationCount, first, last);
205+
206+
// move temp back
207+
pFirst = T_COLOR_FEATURE::getPixelAddress(temp, 0);
208+
pFront = T_COLOR_FEATURE::getPixelAddress(pixels, last - (rotationCount - 1));
209+
while (pFirst <= pLast)
210+
{
211+
T_COLOR_FEATURE::moveIncPixel(pFront, pFirst);
212+
}
213+
214+
Dirty();
215+
}
216+
}
217+
218+
void ShiftLeft(uint16_t shiftCount, uint16_t first = 0, uint16_t last = 0xffff)
219+
{
220+
if (last >= _countPixels)
221+
{
222+
last = _countPixels - 1;
223+
}
224+
225+
if (first < _countPixels &&
226+
last < _countPixels &&
227+
first < last &&
228+
(last - first) >= shiftCount)
229+
{
230+
uint8_t* pixels = _method.getPixels();
231+
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, first);
232+
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(pixels, last);
233+
uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, first + shiftCount);
234+
while (pFront <= pLast)
235+
{
236+
T_COLOR_FEATURE::moveIncPixel(pFirst, pFront);
237+
}
238+
239+
Dirty();
240+
}
241+
}
242+
243+
void RotateRight(uint16_t rotationCount, uint16_t first = 0, uint16_t last = 0xffff)
244+
{
245+
if (last >= _countPixels)
246+
{
247+
last = _countPixels - 1;
248+
}
249+
250+
if (first < _countPixels &&
251+
last < _countPixels &&
252+
first < last &&
253+
(last - first) >= rotationCount)
254+
{
255+
256+
// store in temp
257+
uint8_t temp[rotationCount * T_COLOR_FEATURE::PixelSize];
258+
uint8_t* pixels = _method.getPixels();
259+
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(temp, 0);
260+
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(temp, rotationCount - 1);
261+
uint8_t* pBack = T_COLOR_FEATURE::getPixelAddress(pixels, last);
262+
while (pLast >= pFirst)
263+
{
264+
T_COLOR_FEATURE::moveDecPixel(pLast, pBack);
265+
}
266+
267+
// shift data
268+
ShiftRight(rotationCount, first, last);
269+
270+
// move temp back
271+
pLast = T_COLOR_FEATURE::getPixelAddress(temp, rotationCount - 1);
272+
pBack = T_COLOR_FEATURE::getPixelAddress(pixels, first + rotationCount - 1);
273+
while (pLast >= pFirst)
274+
{
275+
T_COLOR_FEATURE::moveDecPixel(pBack, pLast);
276+
}
277+
278+
Dirty();
279+
}
280+
}
281+
282+
void ShiftRight(uint16_t shiftCount, uint16_t first = 0, uint16_t last = 0xffff)
283+
{
284+
if (last >= _countPixels)
285+
{
286+
last = _countPixels - 1;
287+
}
288+
289+
if (first < _countPixels &&
290+
last < _countPixels &&
291+
first < last &&
292+
(last - first) >= shiftCount)
293+
{
294+
uint8_t* pixels = _method.getPixels();
295+
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, first);
296+
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(pixels, last);
297+
uint8_t* pBack = T_COLOR_FEATURE::getPixelAddress(pixels, last - shiftCount);
298+
while (pBack >= pFirst)
299+
{
300+
T_COLOR_FEATURE::moveDecPixel(pLast, pBack);
301+
}
302+
303+
Dirty();
304+
}
305+
}
306+
171307
private:
172308
const uint16_t _countPixels; // Number of RGB LEDs in strip
173309

src/internal/NeoColorFeatures.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,27 @@ class Neo3Elements
3636
return pPixels + indexPixel * PixelSize;
3737
}
3838

39+
static void copyIncPixel(uint8_t*& pPixelDest, uint8_t* pPixelSrc)
40+
{
41+
*pPixelDest++ = *pPixelSrc++;
42+
*pPixelDest++ = *pPixelSrc++;
43+
*pPixelDest++ = *pPixelSrc;
44+
}
45+
46+
static void moveIncPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
47+
{
48+
*pPixelDest++ = *pPixelSrc++;
49+
*pPixelDest++ = *pPixelSrc++;
50+
*pPixelDest++ = *pPixelSrc++;
51+
}
52+
53+
static void moveDecPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
54+
{
55+
*pPixelDest-- = *pPixelSrc--;
56+
*pPixelDest-- = *pPixelSrc--;
57+
*pPixelDest-- = *pPixelSrc--;
58+
}
59+
3960
typedef RgbColor ColorObject;
4061
};
4162

@@ -49,6 +70,32 @@ class Neo4Elements
4970
return pPixels + indexPixel * PixelSize;
5071
}
5172

73+
static void copyIncPixel(uint8_t*& pPixelDest, uint8_t* pPixelSrc)
74+
{
75+
uint32_t* pDest = (uint32_t*)pPixelDest;
76+
uint32_t* pSrc = (uint32_t*)pPixelSrc;
77+
*pDest++ = *pSrc;
78+
pPixelDest = (uint8_t*)pDest;
79+
}
80+
81+
static void moveIncPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
82+
{
83+
uint32_t* pDest = (uint32_t*)pPixelDest;
84+
uint32_t* pSrc = (uint32_t*)pPixelSrc;
85+
*pDest++ = *pSrc++;
86+
pPixelDest = (uint8_t*)pDest;
87+
pPixelSrc = (uint8_t*)pSrc;
88+
}
89+
90+
static void moveDecPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
91+
{
92+
uint32_t* pDest = (uint32_t*)pPixelDest;
93+
uint32_t* pSrc = (uint32_t*)pPixelSrc;
94+
*pDest-- = *pSrc--;
95+
pPixelDest = (uint8_t*)pDest;
96+
pPixelSrc = (uint8_t*)pSrc;
97+
}
98+
5299
typedef RgbwColor ColorObject;
53100
};
54101

0 commit comments

Comments
 (0)