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