pchestna

L3D Photon Cube Noise

Jan 20th, 2016
296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.39 KB | None | 0 0
  1. // This #include statement was automatically added by the Particle IDE.
  2. #include "FastLED/FastLED.h"
  3.  
  4. FASTLED_USING_NAMESPACE;
  5.  
  6. #define LED_PIN     D0
  7. #define BRIGHTNESS  24
  8. #define LED_TYPE    WS2812B
  9. #define COLOR_ORDER GRB
  10.  
  11. const uint8_t kCubeSize = 8;
  12. const bool    kMatrixSerpentineLayout = false;
  13.  
  14. typedef enum {X_LAYER, Y_LAYER, Z_LAYER} LAYER;
  15. typedef enum {UP, DOWN} DIRECTION;
  16. bool bAnimate = false;
  17.  
  18. // Dictates the direction of the frames
  19. DIRECTION fillDirection = UP;
  20. // Which axis are we filling the frames
  21. LAYER layer = Y_LAYER;
  22. // Which frame number gets the new noise data
  23. int nFillFrame;
  24.  
  25. #define NUM_LEDS (kCubeSize * kCubeSize * kCubeSize)
  26. #define MAX_DIMENSION kCubeSize
  27.  
  28. // The leds
  29. CRGB leds[NUM_LEDS];
  30.  
  31. // The 16 bit version of our coordinates
  32. static uint16_t x;
  33. static uint16_t y;
  34. static uint16_t z;
  35.  
  36. // This example combines two features of FastLED to produce a remarkable range of
  37. // effects from a relatively small amount of code.  This example combines FastLED's
  38. // color palette lookup functions with FastLED's Perlin/simplex noise generator, and
  39. // the combination is extremely powerful.
  40. //
  41. // You might want to look at the "ColorPalette" and "Noise" examples separately
  42. // if this example code seems daunting.
  43. //
  44. // The basic setup here is that for each frame, we generate a new array of
  45. // 'noise' data, and then map it onto the LED matrix through a color palette.
  46. //
  47. // Periodically, the color palette is changed, and new noise-generation parameters
  48. // are chosen at the same time.  In this example, specific noise-generation
  49. // values have been selected to match the given color palettes; some are faster,
  50. // or slower, or larger, or smaller than others, but there's no reason these
  51. // parameters can't be freely mixed-and-matched.
  52. //
  53. // In addition, this example includes some fast automatic 'data smoothing' at
  54. // lower noise speeds to help produce smoother animations in those cases.
  55. //
  56. // The FastLED built-in color palettes (Forest, Clouds, Lava, Ocean, Party) are
  57. // used, as well as some 'hand-defined' ones, and some proceedurally generated
  58. // palettes.
  59.  
  60. // We're using the x/y dimensions to map to the x/y pixels on the matrix.  We'll
  61. // use the z-axis for "time".  speed determines how fast time moves forward.  Try
  62. // 1 for a very slow moving effect, or 60 for something that ends up looking like
  63. // water.
  64. uint16_t speed = 1; // speed is set dynamically once we've started up
  65.  
  66. // Scale determines how far apart the pixels in our noise matrix are.  Try
  67. // changing these values around to see how it affects the motion of the display.  The
  68. // higher the value of scale, the more "zoomed out" the noise will be.  A value
  69. // of 1 will be so zoomed in, you'll mostly see solid colors.
  70. uint16_t scale = 30; // scale is set dynamically once we've started up
  71.  
  72. // This is the array that we keep our computed noise values in
  73. uint8_t noise[MAX_DIMENSION][MAX_DIMENSION];
  74.  
  75. CRGBPalette16 currentPalette( LavaColors_p );
  76. uint8_t       colorLoop = 1;
  77.  
  78. void setup() {
  79.   delay(3000);
  80.   LEDS.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds,NUM_LEDS);
  81.   LEDS.setBrightness(BRIGHTNESS);
  82.  
  83.   // Initialize our coordinates to some random values
  84.   x = random16();
  85.   y = random16();
  86.   z = random16();
  87.  
  88.   if (fillDirection == UP) nFillFrame = 0; else nFillFrame = kCubeSize-1;
  89. }
  90.  
  91. // Fill a frame of the x/y array of 8-bit noise values using the inoise8 function.
  92. void fillnoise8() {
  93.   // If we're runing at a low "speed", some 8-bit artifacts become visible
  94.   // from frame-to-frame.  In order to reduce this, we can do some fast data-smoothing.
  95.   // The amount of data smoothing we're doing depends on "speed".
  96.   uint8_t dataSmoothing = 0;
  97.   if( speed < 50) {
  98.     dataSmoothing = 200 - (speed * 4);
  99.   }
  100.  
  101.   for(int i = 0; i < MAX_DIMENSION; i++) {
  102.     int ioffset = scale * i;
  103.     for(int j = 0; j < MAX_DIMENSION; j++) {
  104.       int joffset = scale * j;
  105.      
  106.       uint8_t data = inoise8(x + ioffset,y + joffset,z);
  107.  
  108.       // The range of the inoise8 function is roughly 16-238.
  109.       // These two operations expand those values out to roughly 0..255
  110.       // You can comment them out if you want the raw noise data.
  111.       data = qsub8(data,16);
  112.       data = qadd8(data,scale8(data,39));
  113.  
  114.       if( dataSmoothing ) {
  115.         uint8_t olddata = noise[i][j];
  116.         uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing);
  117.         data = newdata;
  118.       }
  119.      
  120.       noise[i][j] = data;
  121.     }
  122.   }
  123.  
  124.   z += speed;
  125.  
  126.   // apply slow drift to X and Y, just for visual variation.
  127.   x += speed / 8;
  128.   y -= speed / 16;
  129. }
  130.  
  131. void mapNoiseToLEDsUsingPalette()
  132. {
  133.   static uint8_t ihue=0;
  134.  
  135.   for(int i = 0; i < kCubeSize; i++) {
  136.     for(int j = 0; j < kCubeSize; j++) {
  137.       // We use the value at the (i,j) coordinate in the noise
  138.       // array for our brightness, and the flipped value from (j,i)
  139.       // for our pixel's index into the color palette.
  140.  
  141.       uint8_t index = noise[j][i];
  142.       uint8_t bri =   noise[i][j];
  143.  
  144.       // if this palette is a 'loop', add a slowly-changing base value
  145.       if( colorLoop) {
  146.         index += ihue;
  147.       }
  148.  
  149.       // brighten up, as the color palette itself often contains the
  150.       // light/dark dynamic range desired
  151.       if( bri > 127 ) {
  152.         bri = 255;
  153.       } else {
  154.         bri = dim8_raw( bri * 2);
  155.       }
  156.  
  157.       CRGB color = ColorFromPalette( currentPalette, index, bri);
  158.      
  159.       static int nTo;
  160.       switch (layer)
  161.       {
  162.          case X_LAYER:
  163.            nTo = XYZ(nFillFrame, i, j);
  164.          break;
  165.          case Y_LAYER:
  166.            nTo = XYZ(i, nFillFrame, j);
  167.          break;
  168.          case Z_LAYER:
  169.            nTo = XYZ(i, j, nFillFrame);
  170.          break;
  171.       }
  172.       leds[nTo] = color;
  173.     }
  174.   }
  175.  
  176.   ihue+=1;
  177. }
  178.  
  179. // Copies pixels from one layer to another
  180. void copyLayer(uint8_t fromLayer, uint8_t toLayer);
  181. void copyLayer(uint8_t fromLayer, uint8_t toLayer)
  182. {
  183.   int nFrom; // from pixel
  184.   int nTo; // to pixel
  185.  
  186.   for (int m = 0; m < kCubeSize; m++)
  187.     for (int n = 0; n < kCubeSize; n++)
  188.     {
  189.       switch (layer)
  190.       {
  191.          case X_LAYER:
  192.            nFrom = XYZ(fromLayer, m, n);
  193.            nTo = XYZ(toLayer, m, n);
  194.          break;
  195.          case Y_LAYER:
  196.            nFrom = XYZ(m, fromLayer, n);
  197.            nTo = XYZ(m, toLayer, n);
  198.          break;
  199.          case Z_LAYER:
  200.            nFrom = XYZ(m, n, fromLayer);
  201.            nTo = XYZ(m, n, toLayer);
  202.          break;
  203.       }
  204.       leds[nTo] = leds[nFrom];
  205.     }
  206. }
  207.  
  208. // Copy frames foward in the plane being used from the fillFrame back
  209. void moveFrameForward()
  210. {
  211.   switch (fillDirection)
  212.   {
  213.     case UP:
  214.     {
  215.       for (int nLayer = kCubeSize-1; nLayer > 0; nLayer--)
  216.       {
  217.         if (bAnimate)
  218.           copyLayer(nLayer-1, nLayer);
  219.         else
  220.           copyLayer(nFillFrame, nLayer);
  221.       }
  222.     }
  223.     break;
  224.    
  225.     case DOWN:
  226.     {
  227.       for (int nLayer = 0; nLayer < kCubeSize; nLayer++)
  228.       {
  229.         if (bAnimate)
  230.           copyLayer(nLayer+1, nLayer);
  231.         else
  232.           copyLayer(nFillFrame, nLayer);
  233.       }
  234.     }
  235.     break;
  236.   }
  237. }
  238.  
  239. void loop() {
  240.   // Periodically choose a new palette, speed, and scale
  241.   ChangePaletteAndSettingsPeriodically();
  242.  
  243.   // generate noise data
  244.   fillnoise8();
  245.  
  246.   // convert the noise data to colors in the LED array
  247.   // using the current palette
  248.   mapNoiseToLEDsUsingPalette();
  249.  
  250.   if (bAnimate)
  251.   {
  252.     LEDS.show();
  253.     delay(10);
  254.     // Copy frames
  255.     moveFrameForward();
  256.   }
  257.   else // mirror to other frames
  258.   {
  259.     moveFrameForward();
  260.     LEDS.show();
  261.     delay(10);
  262.   }
  263. }
  264.  
  265.  
  266.  
  267. // There are several different palettes of colors demonstrated here.
  268. //
  269. // FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p,
  270. // OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p.
  271. //
  272. // Additionally, you can manually define your own color palettes, or you can write
  273. // code that creates color palettes on the fly.
  274.  
  275. // 1 = 5 sec per palette
  276. // 2 = 10 sec per palette
  277. // etc
  278. #define HOLD_PALETTES_X_TIMES_AS_LONG 5
  279.  
  280. void ChangePaletteAndSettingsPeriodically()
  281. {
  282.   uint8_t secondHand = ((millis() / 1000) / HOLD_PALETTES_X_TIMES_AS_LONG) % 60;
  283.   static uint8_t lastSecond = 99;
  284.  
  285.   if( lastSecond != secondHand) {
  286.     lastSecond = secondHand;
  287.     if( secondHand ==  0)  { currentPalette = RainbowColors_p;         speed = 1; scale = 30; colorLoop = 1; }
  288.     if( secondHand ==  5)  { SetupPurpleAndGreenPalette();             speed = 1; scale = 50; colorLoop = 1; }
  289.     if( secondHand == 10)  { SetupBlackAndWhiteStripedPalette();       speed = 1; scale = 30; colorLoop = 1; }
  290.     if( secondHand == 15)  { currentPalette = ForestColors_p;          speed = 1; scale =120; colorLoop = 0; }
  291.     if( secondHand == 20)  { currentPalette = CloudColors_p;           speed = 1; scale = 30; colorLoop = 0; }
  292.     if( secondHand == 25)  { currentPalette = LavaColors_p;            speed = 1; scale = 50; colorLoop = 0; }
  293.     if( secondHand == 30)  { currentPalette = OceanColors_p;           speed = 1; scale = 90; colorLoop = 0; }
  294.     if( secondHand == 35)  { currentPalette = PartyColors_p;           speed = 1; scale = 30; colorLoop = 1; }
  295.     if( secondHand == 40)  { SetupRandomPalette();                     speed = 1; scale = 20; colorLoop = 1; }
  296.     if( secondHand == 45)  { SetupRandomPalette();                     speed = 1; scale = 50; colorLoop = 1; }
  297.     if( secondHand == 50)  { SetupRandomPalette();                     speed = 1; scale = 90; colorLoop = 1; }
  298.     if( secondHand == 55)  { currentPalette = RainbowStripeColors_p;   speed = 1; scale = 20; colorLoop = 1; }
  299.   }
  300. }
  301.  
  302. // This function generates a random palette that's a gradient
  303. // between four different colors.  The first is a dim hue, the second is
  304. // a bright hue, the third is a bright pastel, and the last is
  305. // another bright hue.  This gives some visual bright/dark variation
  306. // which is more interesting than just a gradient of different hues.
  307. void SetupRandomPalette()
  308. {
  309.   currentPalette = CRGBPalette16(
  310.                       CHSV( random8(), 255, 32),
  311.                       CHSV( random8(), 255, 255),
  312.                       CHSV( random8(), 128, 255),
  313.                       CHSV( random8(), 255, 255));
  314. }
  315.  
  316. // This function sets up a palette of black and white stripes,
  317. // using code.  Since the palette is effectively an array of
  318. // sixteen CRGB colors, the various fill_* functions can be used
  319. // to set them up.
  320. void SetupBlackAndWhiteStripedPalette()
  321. {
  322.   // 'black out' all 16 palette entries...
  323.   fill_solid( currentPalette, 16, CRGB::Black);
  324.   // and set every fourth one to white.
  325.   currentPalette[0] = CRGB::White;
  326.   currentPalette[4] = CRGB::White;
  327.   currentPalette[8] = CRGB::White;
  328.   currentPalette[12] = CRGB::White;
  329.  
  330. }
  331.  
  332. // This function sets up a palette of purple and green stripes.
  333. void SetupPurpleAndGreenPalette()
  334. {
  335.   CRGB purple = CHSV( HUE_PURPLE, 255, 255);
  336.   CRGB green  = CHSV( HUE_GREEN, 255, 255);
  337.   CRGB black  = CRGB::Black;
  338.  
  339.   currentPalette = CRGBPalette16(
  340.     green,  green,  black,  black,
  341.     purple, purple, black,  black,
  342.     green,  green,  black,  black,
  343.     purple, purple, black,  black );
  344. }
  345.  
  346. //
  347. // xyz coordinate mapping code
  348. //
  349. uint16_t XYZ( uint8_t x, uint8_t y, uint8_t z)
  350. {
  351.   uint16_t i;
  352.  
  353.   i = 8 * ((y * kCubeSize) + x) + z;
  354.  
  355.   if ((i >= 0) && (i <= 512))
  356.     return i;
  357.   else
  358.     return 0;
  359. }
Advertisement
Add Comment
Please, Sign In to add comment