FastLED 3.9.7
Loading...
Searching...
No Matches
XYMatrix.ino
Go to the documentation of this file.
1
4
5#include <FastLED.h>
6
7#define LED_PIN 3
8
9#define COLOR_ORDER GRB
10#define CHIPSET WS2811
11
12#define BRIGHTNESS 64
13
14// Helper functions for an two-dimensional XY matrix of pixels.
15// Simple 2-D demo code is included as well.
16//
17// XY(x,y) takes x and y coordinates and returns an LED index number,
18// for use like this: leds[ XY(x,y) ] == CRGB::Red;
19// No error checking is performed on the ranges of x and y.
20//
21// XYsafe(x,y) takes x and y coordinates and returns an LED index number,
22// for use like this: leds[ XYsafe(x,y) ] == CRGB::Red;
23// Error checking IS performed on the ranges of x and y, and an
24// index of "-1" is returned. Special instructions below
25// explain how to use this without having to do your own error
26// checking every time you use this function.
27// This is a slightly more advanced technique, and
28// it REQUIRES SPECIAL ADDITIONAL setup, described below.
29
30
31// Params for width and height
32const uint8_t kMatrixWidth = 16;
33const uint8_t kMatrixHeight = 16;
34
35// Param for different pixel layouts
36const bool kMatrixSerpentineLayout = true;
37const bool kMatrixVertical = false;
38
39// Set 'kMatrixSerpentineLayout' to false if your pixels are
40// laid out all running the same way, like this:
41//
42// 0 > 1 > 2 > 3 > 4
43// |
44// .----<----<----<----'
45// |
46// 5 > 6 > 7 > 8 > 9
47// |
48// .----<----<----<----'
49// |
50// 10 > 11 > 12 > 13 > 14
51// |
52// .----<----<----<----'
53// |
54// 15 > 16 > 17 > 18 > 19
55//
56// Set 'kMatrixSerpentineLayout' to true if your pixels are
57// laid out back-and-forth, like this:
58//
59// 0 > 1 > 2 > 3 > 4
60// |
61// |
62// 9 < 8 < 7 < 6 < 5
63// |
64// |
65// 10 > 11 > 12 > 13 > 14
66// |
67// |
68// 19 < 18 < 17 < 16 < 15
69//
70// Bonus vocabulary word: anything that goes one way
71// in one row, and then backwards in the next row, and so on
72// is call "boustrophedon", meaning "as the ox plows."
73
74
75// This function will return the right 'led index number' for
76// a given set of X and Y coordinates on your matrix.
77// IT DOES NOT CHECK THE COORDINATE BOUNDARIES.
78// That's up to you. Don't pass it bogus values.
79//
80// Use the "XY" function like this:
81//
82// for( uint8_t x = 0; x < kMatrixWidth; x++) {
83// for( uint8_t y = 0; y < kMatrixHeight; y++) {
84//
85// // Here's the x, y to 'led index' in action:
86// leds[ XY( x, y) ] = CHSV( random8(), 255, 255);
87//
88// }
89// }
90//
91//
92uint16_t XY( uint8_t x, uint8_t y)
93{
94 uint16_t i;
95
96 if( kMatrixSerpentineLayout == false) {
97 if (kMatrixVertical == false) {
98 i = (y * kMatrixWidth) + x;
99 } else {
100 i = kMatrixHeight * (kMatrixWidth - (x+1))+y;
101 }
102 }
103
104 if( kMatrixSerpentineLayout == true) {
105 if (kMatrixVertical == false) {
106 if( y & 0x01) {
107 // Odd rows run backwards
108 uint8_t reverseX = (kMatrixWidth - 1) - x;
109 i = (y * kMatrixWidth) + reverseX;
110 } else {
111 // Even rows run forwards
112 i = (y * kMatrixWidth) + x;
113 }
114 } else { // vertical positioning
115 if ( x & 0x01) {
116 i = kMatrixHeight * (kMatrixWidth - (x+1))+y;
117 } else {
118 i = kMatrixHeight * (kMatrixWidth - x) - (y+1);
119 }
120 }
121 }
122
123 return i;
124}
125
126
127// Once you've gotten the basics working (AND NOT UNTIL THEN!)
128// here's a helpful technique that can be tricky to set up, but
129// then helps you avoid the needs for sprinkling array-bound-checking
130// throughout your code.
131//
132// It requires a careful attention to get it set up correctly, but
133// can potentially make your code smaller and faster.
134//
135// Suppose you have an 8 x 5 matrix of 40 LEDs. Normally, you'd
136// delcare your leds array like this:
137// CRGB leds[40];
138// But instead of that, declare an LED buffer with one extra pixel in
139// it, "leds_plus_safety_pixel". Then declare "leds" as a pointer to
140// that array, but starting with the 2nd element (id=1) of that array:
141// CRGB leds_with_safety_pixel[41];
142// CRGB* const leds( leds_plus_safety_pixel + 1);
143// Then you use the "leds" array as you normally would.
144// Now "leds[0..N]" are aliases for "leds_plus_safety_pixel[1..(N+1)]",
145// AND leds[-1] is now a legitimate and safe alias for leds_plus_safety_pixel[0].
146// leds_plus_safety_pixel[0] aka leds[-1] is now your "safety pixel".
147//
148// Now instead of using the XY function above, use the one below, "XYsafe".
149//
150// If the X and Y values are 'in bounds', this function will return an index
151// into the visible led array, same as "XY" does.
152// HOWEVER -- and this is the trick -- if the X or Y values
153// are out of bounds, this function will return an index of -1.
154// And since leds[-1] is actually just an alias for leds_plus_safety_pixel[0],
155// it's a totally safe and legal place to access. And since the 'safety pixel'
156// falls 'outside' the visible part of the LED array, anything you write
157// there is hidden from view automatically.
158// Thus, this line of code is totally safe, regardless of the actual size of
159// your matrix:
160// leds[ XYsafe( random8(), random8() ) ] = CHSV( random8(), 255, 255);
161//
162// The only catch here is that while this makes it safe to read from and
163// write to 'any pixel', there's really only ONE 'safety pixel'. No matter
164// what out-of-bounds coordinates you write to, you'll really be writing to
165// that one safety pixel. And if you try to READ from the safety pixel,
166// you'll read whatever was written there last, reglardless of what coordinates
167// were supplied.
168
169#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
170CRGB leds_plus_safety_pixel[ NUM_LEDS + 1];
171CRGB* const leds( leds_plus_safety_pixel + 1);
172
173uint16_t XYsafe( uint8_t x, uint8_t y)
174{
175 if( x >= kMatrixWidth) return -1;
176 if( y >= kMatrixHeight) return -1;
177 return XY(x,y);
178}
179
180
181void DrawOneFrame( uint8_t startHue8, int8_t yHueDelta8, int8_t xHueDelta8)
182{
183 uint8_t lineStartHue = startHue8;
184 for( uint8_t y = 0; y < kMatrixHeight; y++) {
185 lineStartHue += yHueDelta8;
186 uint8_t pixelHue = lineStartHue;
187 for( uint8_t x = 0; x < kMatrixWidth; x++) {
188 pixelHue += xHueDelta8;
189 leds[ XY(x, y)] = CHSV( pixelHue, 255, 255);
190 }
191 }
192}
193
194
195void setup() {
196 FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
197 FastLED.setBrightness( BRIGHTNESS );
198}
199
200
201// Demo that USES "XY" follows code below
202
203void loop()
204{
205 uint32_t ms = millis();
206 int32_t yHueDelta32 = ((int32_t)cos16( ms * (27/1) ) * (350 / kMatrixWidth));
207 int32_t xHueDelta32 = ((int32_t)cos16( ms * (39/1) ) * (310 / kMatrixHeight));
208 DrawOneFrame( ms / 65536, yHueDelta32 / 32768, xHueDelta32 / 32768);
209 if( ms < 5000 ) {
210 FastLED.setBrightness( scale8( BRIGHTNESS, (ms * 256) / 5000));
211 } else {
212 FastLED.setBrightness(BRIGHTNESS);
213 }
214 FastLED.show();
215}
216
217
CFastLED FastLED
Global LED strip management instance.
Definition FastLED.cpp:45
central include file for FastLED, defines the CFastLED class/object
void setBrightness(uint8_t scale)
Set the global brightness scaling.
Definition FastLED.h:723
void show(uint8_t scale)
Update all our controllers with the current led colors, using the passed in brightness.
Definition FastLED.cpp:94
static CLEDController & addLeds(CLEDController *pLed, struct CRGB *data, int nLedsOrOffset, int nLedsIfOffset=0)
Add a CLEDController instance to the world.
Definition FastLED.cpp:79
@ TypicalSMD5050
Typical values for SMD5050 LEDs.
Definition color.h:17
LIB8STATIC_ALWAYS_INLINE uint8_t scale8(uint8_t i, fract8 scale)
Scale one byte by a second one, which is treated as the numerator of a fraction whose denominator is ...
Definition scale8.h:34
LIB8STATIC int16_t cos16(uint16_t theta)
Fast 16-bit approximation of cos(x).
Definition trig8.h:135
Representation of an HSV pixel (hue, saturation, value (aka brightness)).
Definition chsv.h:16
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:54