|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- #include <FastLED.h>
-
- #define LED_PIN 3
-
- #define COLOR_ORDER GRB
- #define CHIPSET WS2811
-
- #define BRIGHTNESS 64
-
- // Helper functions for an two-dimensional XY matrix of pixels.
- // Simple 2-D demo code is included as well.
- //
- // XY(x,y) takes x and y coordinates and returns an LED index number,
- // for use like this: leds[ XY(x,y) ] == CRGB::Red;
- // No error checking is performed on the ranges of x and y.
- //
- // XYsafe(x,y) takes x and y coordinates and returns an LED index number,
- // for use like this: leds[ XY(x,y) ] == CRGB::Red;
- // Error checking IS performed on the ranges of x and y, and an
- // index of "-1" is returned. Special instructions below
- // explain how to use this without having to do your own error
- // checking every time you use this function.
- // This is a slightly more advanced technique, and
- // it REQUIRES SPECIAL ADDITIONAL setup, described below.
-
-
- // Params for width and height
- const uint8_t kMatrixWidth = 16;
- const uint8_t kMatrixHeight = 16;
-
- // Param for different pixel layouts
- const bool kMatrixSerpentineLayout = true;
- // Set 'kMatrixSerpentineLayout' to false if your pixels are
- // laid out all running the same way, like this:
- //
- // 0 > 1 > 2 > 3 > 4
- // |
- // .----<----<----<----'
- // |
- // 5 > 6 > 7 > 8 > 9
- // |
- // .----<----<----<----'
- // |
- // 10 > 11 > 12 > 13 > 14
- // |
- // .----<----<----<----'
- // |
- // 15 > 16 > 17 > 18 > 19
- //
- // Set 'kMatrixSerpentineLayout' to true if your pixels are
- // laid out back-and-forth, like this:
- //
- // 0 > 1 > 2 > 3 > 4
- // |
- // |
- // 9 < 8 < 7 < 6 < 5
- // |
- // |
- // 10 > 11 > 12 > 13 > 14
- // |
- // |
- // 19 < 18 < 17 < 16 < 15
- //
- // Bonus vocabulary word: anything that goes one way
- // in one row, and then backwards in the next row, and so on
- // is call "boustrophedon", meaning "as the ox plows."
-
-
- // This function will return the right 'led index number' for
- // a given set of X and Y coordinates on your matrix.
- // IT DOES NOT CHECK THE COORDINATE BOUNDARIES.
- // That's up to you. Don't pass it bogus values.
- //
- // Use the "XY" function like this:
- //
- // for( uint8_t x = 0; x < kMatrixWidth; x++) {
- // for( uint8_t y = 0; y < kMatrixHeight; y++) {
- //
- // // Here's the x, y to 'led index' in action:
- // leds[ XY( x, y) ] = CHSV( random8(), 255, 255);
- //
- // }
- // }
- //
- //
- uint16_t XY( uint8_t x, uint8_t y)
- {
- uint16_t i;
-
- if( kMatrixSerpentineLayout == false) {
- i = (y * kMatrixWidth) + x;
- }
-
- if( kMatrixSerpentineLayout == true) {
- if( y & 0x01) {
- // Odd rows run backwards
- uint8_t reverseX = (kMatrixWidth - 1) - x;
- i = (y * kMatrixWidth) + reverseX;
- } else {
- // Even rows run forwards
- i = (y * kMatrixWidth) + x;
- }
- }
-
- return i;
- }
-
-
- // Once you've gotten the basics working (AND NOT UNTIL THEN!)
- // here's a helpful technique that can be tricky to set up, but
- // then helps you avoid the needs for sprinkling array-bound-checking
- // throughout your code.
- //
- // It requires a careful attention to get it set up correctly, but
- // can potentially make your code smaller and faster.
- //
- // Suppose you have an 8 x 5 matrix of 40 LEDs. Normally, you'd
- // delcare your leds array like this:
- // CRGB leds[40];
- // But instead of that, declare an LED buffer with one extra pixel in
- // it, "leds_plus_safety_pixel". Then declare "leds" as a pointer to
- // that array, but starting with the 2nd element (id=1) of that array:
- // CRGB leds_with_safety_pixel[41];
- // CRGB* const leds( leds_plus_safety_pixel + 1);
- // Then you use the "leds" array as you normally would.
- // Now "leds[0..N]" are aliases for "leds_plus_safety_pixel[1..(N+1)]",
- // AND leds[-1] is now a legitimate and safe alias for leds_plus_safety_pixel[0].
- // leds_plus_safety_pixel[0] aka leds[-1] is now your "safety pixel".
- //
- // Now instead of using the XY function above, use the one below, "XYsafe".
- //
- // If the X and Y values are 'in bounds', this function will return an index
- // into the visible led array, same as "XY" does.
- // HOWEVER -- and this is the trick -- if the X or Y values
- // are out of bounds, this function will return an index of -1.
- // And since leds[-1] is actually just an alias for leds_plus_safety_pixel[0],
- // it's a totally safe and legal place to access. And since the 'safety pixel'
- // falls 'outside' the visible part of the LED array, anything you write
- // there is hidden from view automatically.
- // Thus, this line of code is totally safe, regardless of the actual size of
- // your matrix:
- // leds[ XYsafe( random8(), random8() ) ] = CHSV( random8(), 255, 255);
- //
- // The only catch here is that while this makes it safe to read from and
- // write to 'any pixel', there's really only ONE 'safety pixel'. No matter
- // what out-of-bounds coordinates you write to, you'll really be writing to
- // that one safety pixel. And if you try to READ from the safety pixel,
- // you'll read whatever was written there last, reglardless of what coordinates
- // were supplied.
-
- #define NUM_LEDS (kMatrixWidth * kMatrixHeight)
- CRGB leds_plus_safety_pixel[ NUM_LEDS + 1];
- CRGB* const leds( leds_plus_safety_pixel + 1);
-
- uint16_t XYsafe( uint8_t x, uint8_t y)
- {
- if( x >= kMatrixWidth) return -1;
- if( y >= kMatrixHeight) return -1;
- return XY(x,y);
- }
-
-
- // Demo that USES "XY" follows code below
-
- void loop()
- {
- uint32_t ms = millis();
- int32_t yHueDelta32 = ((int32_t)cos16( ms * (27/1) ) * (350 / kMatrixWidth));
- int32_t xHueDelta32 = ((int32_t)cos16( ms * (39/1) ) * (310 / kMatrixHeight));
- DrawOneFrame( ms / 65536, yHueDelta32 / 32768, xHueDelta32 / 32768);
- if( ms < 5000 ) {
- FastLED.setBrightness( scale8( BRIGHTNESS, (ms * 256) / 5000));
- } else {
- FastLED.setBrightness(BRIGHTNESS);
- }
- FastLED.show();
- }
-
- void DrawOneFrame( byte startHue8, int8_t yHueDelta8, int8_t xHueDelta8)
- {
- byte lineStartHue = startHue8;
- for( byte y = 0; y < kMatrixHeight; y++) {
- lineStartHue += yHueDelta8;
- byte pixelHue = lineStartHue;
- for( byte x = 0; x < kMatrixWidth; x++) {
- pixelHue += xHueDelta8;
- leds[ XY(x, y)] = CHSV( pixelHue, 255, 255);
- }
- }
- }
-
-
- void setup() {
- FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
- FastLED.setBrightness( BRIGHTNESS );
- }
|