utils.h
  1  // SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries
  2  //
  3  // SPDX-License-Identifier: MIT
  4  
  5  // Assorted useful functions and variables
  6  
  7  // Global variables
  8  boolean effectInit = false;   // indicates if a pattern has been recently switched
  9  uint16_t effectDelay = 0;   // time between automatic effect changes
 10  unsigned long effectMillis = 0;   // store the time of last effect function run
 11  unsigned long cycleMillis = 0;    // store the time of last effect change
 12  unsigned long currentMillis;    // store current loop's millis value
 13  unsigned long hueMillis;    // store time of last hue change
 14  byte currentEffect = 0;   // index to the currently running effect
 15  boolean autoCycle = true;   // flag for automatic effect changes
 16  byte currentBrightness = STARTBRIGHTNESS;   // 0-255 will be scaled to 0-MAXBRIGHTNESS
 17  
 18  
 19  //  Setup information for the NoisePlusPalette noiseplay example
 20  #define MAX_DIMENSION ((kMatrixWidth>kMatrixHeight) ? kMatrixWidth : kMatrixHeight)
 21  uint16_t speed = 5; 
 22  uint16_t scale = 30;
 23  uint8_t noise[MAX_DIMENSION][MAX_DIMENSION];
 24  
 25  // The 16 bit version of our coordinates
 26  static uint16_t x;
 27  static uint16_t y;
 28  static uint16_t z;
 29  uint8_t       colorLoop = 1;
 30  
 31  
 32  CRGBPalette16 currentPalette(RainbowColors_p); // global palette storage
 33  
 34  typedef void (*functionList)(); // definition for list of effect function pointers
 35  extern const byte numEffects;
 36  
 37  // Increment the global hue value for functions that use it
 38  byte cycleHue = 0;
 39  byte cycleHueCount = 0;
 40  void hueCycle(byte incr) {
 41      cycleHueCount = 0;
 42      cycleHue+=incr;
 43  }
 44  
 45  // Set every LED in the array to a specified color
 46  void fillAll(CRGB fillColor) {
 47    for (byte i = 0; i < NUM_LEDS; i++) {
 48      leds[i] = fillColor;
 49    }
 50  }
 51  
 52  // Fade every LED in the array by a specified amount
 53  void fadeAll(byte fadeIncr) {
 54    for (byte i = 0; i < NUM_LEDS; i++) {
 55      leds[i] = leds[i].fadeToBlackBy(fadeIncr);
 56    }
 57  }
 58  
 59  // Shift all pixels by one, right or left (0 or 1)
 60  void scrollArray(byte scrollDir) {
 61    
 62      byte scrollX = 0;
 63      for (byte x = 1; x < kMatrixWidth; x++) {
 64        if (scrollDir == 0) {
 65          scrollX = kMatrixWidth - x;
 66        } else if (scrollDir == 1) {
 67          scrollX = x - 1;
 68        }
 69        
 70        for (byte y = 0; y < kMatrixHeight; y++) {
 71          leds[XY(scrollX,y)] = leds[XY(scrollX + scrollDir*2 - 1,y)];
 72        }
 73      }
 74    
 75  }
 76  
 77  
 78  // Pick a random palette from a list
 79  void selectRandomPalette() {
 80  
 81    switch(random8(8)) {
 82      case 0:
 83      currentPalette = CloudColors_p;
 84      break;
 85      
 86      case 1:
 87      currentPalette = LavaColors_p;
 88      break;
 89      
 90      case 2:
 91      currentPalette = OceanColors_p;
 92      break;
 93      
 94      case 4:
 95      currentPalette = ForestColors_p;
 96      break;
 97      
 98      case 5:
 99      currentPalette = RainbowColors_p;
100      break;
101      
102      case 6:
103      currentPalette = PartyColors_p;
104      break;
105      
106      case 7:
107      currentPalette = HeatColors_p;
108      break;
109    }
110  
111  }
112  
113   // Fill the x/y array of 8-bit noise values using the inoise8 function.
114  void fillnoise8() {
115    // If we're runing at a low "speed", some 8-bit artifacts become visible
116    // from frame-to-frame.  In order to reduce this, we can do some fast data-smoothing.
117    // The amount of data smoothing we're doing depends on "speed".
118    uint8_t dataSmoothing = 0;
119    if( speed < 50) {
120      dataSmoothing = 200 - (speed * 4);
121    }
122    
123    for(int i = 0; i < MAX_DIMENSION; i++) {
124      int ioffset = scale * i;
125      for(int j = 0; j < MAX_DIMENSION; j++) {
126        int joffset = scale * j;
127        
128        uint8_t data = inoise8(x + ioffset,y + joffset,z);
129  
130        // The range of the inoise8 function is roughly 16-238.
131        // These two operations expand those values out to roughly 0..255
132        // You can comment them out if you want the raw noise data.
133        data = qsub8(data,16);
134        data = qadd8(data,scale8(data,39));
135  
136        if( dataSmoothing ) {
137          uint8_t olddata = noise[i][j];
138          uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing);
139          data = newdata;
140        }
141        
142        noise[i][j] = data;
143      }
144    }
145    
146    z += speed;
147    
148    // apply slow drift to X and Y, just for visual variation.
149    x += speed / 8;
150    y -= speed / 16;
151  }
152  
153  void mapNoiseToLEDsUsingPalette()
154  {
155    static uint8_t ihue=0;
156    
157    for(int i = 0; i < kMatrixWidth; i++) {
158      for(int j = 0; j < kMatrixHeight; j++) {
159        // We use the value at the (i,j) coordinate in the noise
160        // array for our brightness, and the flipped value from (j,i)
161        // for our pixel's index into the color palette.
162  
163        uint8_t index = noise[j][i];
164        uint8_t bri =   noise[i][j];
165  
166        // if this palette is a 'loop', add a slowly-changing base value
167        if( colorLoop) { 
168          index += ihue;
169        }
170  
171        // brighten up, as the color palette itself often contains the 
172        // light/dark dynamic range desired
173        if( bri > 127 ) {
174          bri = 255;
175        } else {
176          bri = dim8_raw( bri * 2);
177        }
178  
179        CRGB color = ColorFromPalette( currentPalette, index, bri);
180        leds[XY(i,j)] = color;
181      }
182    }
183    
184    ihue+=1;
185  }