├── Commands.h ├── GradientPalettes.h ├── LICENSE ├── Life.h ├── Noise.h ├── README.md ├── Twinkles.h └── fibonacci-v3d.ino /Commands.h: -------------------------------------------------------------------------------- 1 | /* 2 | Fibonacci v3D: https://github.com/evilgeniuslabs/fibonacci-v3d 3 | Copyright (C) 2014-2016 Jason Coon, Evil Genius Labs 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef IrCodes_H 20 | #define IrCodes_H 21 | 22 | enum class InputCommand { 23 | None, 24 | Up, 25 | Down, 26 | Left, 27 | Right, 28 | Select, 29 | Brightness, 30 | PlayMode, 31 | Palette, 32 | Power, 33 | BrightnessUp, 34 | BrightnessDown, 35 | 36 | Pattern1, 37 | Pattern2, 38 | Pattern3, 39 | Pattern4, 40 | Pattern5, 41 | Pattern6, 42 | Pattern7, 43 | Pattern8, 44 | Pattern9, 45 | Pattern10, 46 | Pattern11, 47 | Pattern12, 48 | 49 | RedUp, 50 | RedDown, 51 | GreenUp, 52 | GreenDown, 53 | BlueUp, 54 | BlueDown, 55 | 56 | Red, 57 | RedOrange, 58 | Orange, 59 | YellowOrange, 60 | Yellow, 61 | 62 | Green, 63 | Lime, 64 | Aqua, 65 | Teal, 66 | Navy, 67 | 68 | Blue, 69 | RoyalBlue, 70 | Purple, 71 | Indigo, 72 | Magenta, 73 | 74 | White, 75 | Pink, 76 | LightPink, 77 | BabyBlue, 78 | LightBlue, 79 | }; 80 | 81 | // IR Raw Key Codes for SparkFun remote 82 | #define IRCODE_SPARKFUN_POWER 0x10EFD827 // 284153895 83 | #define IRCODE_SPARKFUN_A 0x10EFF807 // 84 | #define IRCODE_SPARKFUN_B 0x10EF7887 85 | #define IRCODE_SPARKFUN_C 0x10EF58A7 86 | #define IRCODE_SPARKFUN_UP 0x10EFA05F // 284139615 87 | #define IRCODE_SPARKFUN_LEFT 0x10EF10EF 88 | #define IRCODE_SPARKFUN_SELECT 0x10EF20DF 89 | #define IRCODE_SPARKFUN_RIGHT 0x10EF807F 90 | #define IRCODE_SPARKFUN_DOWN 0x10EF00FF 91 | #define IRCODE_SPARKFUN_HELD 0xFFFFFFFF 92 | 93 | // IR Raw Key Codes for Adafruit remote 94 | #define IRCODE_ADAFRUIT_HELD 0x7FFFFFFF // 4294967295 95 | #define IRCODE_ADAFRUIT_VOLUME_UP 0x00FD40BF // 16597183 96 | #define IRCODE_ADAFRUIT_PLAY_PAUSE 0x00FD807F // 16613503 97 | #define IRCODE_ADAFRUIT_VOLUME_DOWN 0x00FD00FF // 16580863 98 | #define IRCODE_ADAFRUIT_SETUP 0x00FD20DF // 16589023 99 | #define IRCODE_ADAFRUIT_UP 0x00FDA05F // 16621663 100 | #define IRCODE_ADAFRUIT_STOP_MODE 0x00FD609F // 16605343 101 | #define IRCODE_ADAFRUIT_LEFT 0x00FD10EF // 16584943 102 | #define IRCODE_ADAFRUIT_ENTER_SAVE 0x00FD906F // 16617583 103 | #define IRCODE_ADAFRUIT_RIGHT 0x00FD50AF // 16601263 104 | #define IRCODE_ADAFRUIT_0_10_PLUS 0x00FD30CF // 16593103 105 | #define IRCODE_ADAFRUIT_DOWN 0x00FDB04F // 16625743 106 | #define IRCODE_ADAFRUIT_BACK 0x00FD708F // 16609423 107 | #define IRCODE_ADAFRUIT_1 0x00FD08F7 // 16582903 108 | #define IRCODE_ADAFRUIT_2 0x00FD8877 // 16615543 109 | #define IRCODE_ADAFRUIT_3 0x00FD48B7 // 16599223 110 | #define IRCODE_ADAFRUIT_4 0x00FD28D7 // 16591063 111 | #define IRCODE_ADAFRUIT_5 0x00FDA857 // 16623703 112 | #define IRCODE_ADAFRUIT_6 0x00FD6897 // 16607383 113 | #define IRCODE_ADAFRUIT_7 0x00FD18E7 // 16586983 114 | #define IRCODE_ADAFRUIT_8 0x00FD9867 // 16619623 115 | #define IRCODE_ADAFRUIT_9 0x00FD58A7 // 16603303 116 | 117 | // IR Raw Key Codes for eTopxizu 44Key IR Remote Controller for 5050 3528 RGB LED Light Strip 118 | #define IRCODE_ETOPXIZU_HELD 0x7FFFFFFF // 4294967295 119 | #define IRCODE_ETOPXIZU_POWER 16712445 120 | #define IRCODE_ETOPXIZU_PLAY_PAUSE 16745085 121 | #define IRCODE_ETOPXIZU_BRIGHTNESS_UP 16726725 122 | #define IRCODE_ETOPXIZU_BRIGHTNESS_DOWN 16759365 123 | 124 | #define IRCODE_ETOPXIZU_DIY1 16724175 125 | #define IRCODE_ETOPXIZU_DIY2 16756815 126 | #define IRCODE_ETOPXIZU_DIY3 16740495 127 | #define IRCODE_ETOPXIZU_DIY4 16716015 128 | #define IRCODE_ETOPXIZU_DIY5 16748655 129 | #define IRCODE_ETOPXIZU_DIY6 16732335 130 | 131 | #define IRCODE_ETOPXIZU_JUMP3 16720095 132 | #define IRCODE_ETOPXIZU_JUMP7 16752735 133 | #define IRCODE_ETOPXIZU_FADE3 16736415 134 | #define IRCODE_ETOPXIZU_FADE7 16769055 135 | #define IRCODE_ETOPXIZU_FLASH 16764975 136 | #define IRCODE_ETOPXIZU_AUTO 16773135 137 | 138 | #define IRCODE_ETOPXIZU_QUICK 16771095 139 | #define IRCODE_ETOPXIZU_SLOW 16762935 140 | 141 | #define IRCODE_ETOPXIZU_RED_UP 16722135 142 | #define IRCODE_ETOPXIZU_RED_DOWN 16713975 143 | 144 | #define IRCODE_ETOPXIZU_GREEN_UP 16754775 145 | #define IRCODE_ETOPXIZU_GREEN_DOWN 16746615 146 | 147 | #define IRCODE_ETOPXIZU_BLUE_UP 16738455 148 | #define IRCODE_ETOPXIZU_BLUE_DOWN 16730295 149 | 150 | #define IRCODE_ETOPXIZU_RED 16718565 151 | #define IRCODE_ETOPXIZU_RED_ORANGE 16722645 152 | #define IRCODE_ETOPXIZU_ORANGE 16714485 153 | #define IRCODE_ETOPXIZU_YELLOW_ORANGE 16726215 154 | #define IRCODE_ETOPXIZU_YELLOW 16718055 155 | 156 | #define IRCODE_ETOPXIZU_GREEN 16751205 157 | #define IRCODE_ETOPXIZU_LIME 16755285 158 | #define IRCODE_ETOPXIZU_AQUA 16747125 159 | #define IRCODE_ETOPXIZU_TEAL 16758855 160 | #define IRCODE_ETOPXIZU_NAVY 16750695 161 | 162 | #define IRCODE_ETOPXIZU_BLUE 16753245 163 | #define IRCODE_ETOPXIZU_ROYAL_BLUE 16749165 164 | #define IRCODE_ETOPXIZU_PURPLE 16757325 165 | #define IRCODE_ETOPXIZU_INDIGO 16742535 166 | #define IRCODE_ETOPXIZU_MAGENTA 16734375 167 | 168 | #define IRCODE_ETOPXIZU_WHITE 16720605 169 | #define IRCODE_ETOPXIZU_PINK 16716525 170 | #define IRCODE_ETOPXIZU_LIGHT_PINK 16724685 171 | #define IRCODE_ETOPXIZU_BABY_BLUE 16775175 172 | #define IRCODE_ETOPXIZU_LIGHT_BLUE 16767015 173 | 174 | bool sparkfunRemoteEnabled = false; 175 | bool adafruitRemoteEnabled = true; 176 | bool etopxizuRemoteEnabled = true; 177 | 178 | // Dumps out the decode_results structure. 179 | // Call this after IRrecv::decode() 180 | // void * to work around compiler issue 181 | //void dump(void *v) { 182 | // decode_results *results = (decode_results *)v 183 | void dump(decode_results *results) { 184 | int count = results->rawlen; 185 | if (results->decode_type == UNKNOWN) { 186 | Serial.print("Unknown encoding: "); 187 | } 188 | else if (results->decode_type == NEC) { 189 | Serial.print("Decoded NEC: "); 190 | } 191 | else if (results->decode_type == SONY) { 192 | Serial.print("Decoded SONY: "); 193 | } 194 | else if (results->decode_type == RC5) { 195 | Serial.print("Decoded RC5: "); 196 | } 197 | else if (results->decode_type == RC6) { 198 | Serial.print("Decoded RC6: "); 199 | } 200 | else if (results->decode_type == PANASONIC) { 201 | Serial.print("Decoded PANASONIC - Address: "); 202 | Serial.print(results->panasonicAddress,HEX); 203 | Serial.print(" Value: "); 204 | } 205 | else if (results->decode_type == JVC) { 206 | Serial.print("Decoded JVC: "); 207 | } 208 | Serial.print(results->value, HEX); 209 | Serial.print(" ("); 210 | Serial.print(results->bits, DEC); 211 | Serial.println(" bits)"); 212 | Serial.print("Raw ("); 213 | Serial.print(count, DEC); 214 | Serial.print("): "); 215 | 216 | for (int i = 0; i < count; i++) { 217 | if ((i % 2) == 1) { 218 | Serial.print(results->rawbuf[i]*USECPERTICK, DEC); 219 | } 220 | else { 221 | Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC); 222 | } 223 | Serial.print(" "); 224 | } 225 | Serial.println(""); 226 | } 227 | 228 | // Low level IR code reading function 229 | // Function will return 0 if no IR code available 230 | unsigned long decodeIRCode() { 231 | 232 | decode_results results; 233 | 234 | results.value = 0; 235 | 236 | // Attempt to read an IR code ? 237 | if (irReceiver.decode(&results)) { 238 | delay(20); 239 | 240 | if (results.value != 0) 241 | Serial.println(results.value); 242 | 243 | dump(&results); 244 | 245 | // Prepare to receive the next IR code 246 | irReceiver.resume(); 247 | } 248 | 249 | return results.value; 250 | } 251 | 252 | // Read an IR code 253 | // Function will return 0 if no IR code available 254 | unsigned long readIRCode() { 255 | 256 | // Is there an IR code to read ? 257 | unsigned long code = decodeIRCode(); 258 | if (code == 0) { 259 | // No code so return 0 260 | return 0; 261 | } 262 | 263 | // Keep reading until code changes 264 | while (decodeIRCode() == code) { 265 | ; 266 | } 267 | // Serial.println(code); 268 | return code; 269 | } 270 | 271 | unsigned long lastIrCode = 0; 272 | 273 | unsigned int holdStartTime = 0; 274 | unsigned int defaultHoldDelay = 500; 275 | bool isHolding = false; 276 | 277 | unsigned int zeroStartTime = 0; 278 | unsigned int zeroDelay = 120; 279 | 280 | unsigned long readIRCode(unsigned int holdDelay) { 281 | // read the raw code from the sensor 282 | unsigned long irCode = readIRCode(); 283 | 284 | //Serial.print(millis()); 285 | //Serial.print("\t"); 286 | //Serial.println(irCode); 287 | 288 | // don't return a short click until we know it's not a long hold 289 | // we'll have to wait for holdDelay ms to pass before returning a non-zero IR code 290 | // then, after that delay, as long as the button is held, we can keep returning the code 291 | // every time until it's released 292 | 293 | // the ir remote only sends codes every 107 ms or so (avg 106.875, max 111, min 102), 294 | // so the ir sensor will return 0 even if a button is held 295 | // so we have to wait longer than that before returning a non-zero code 296 | // in order to detect that a button has been released and is no longer held 297 | 298 | // only reset after we've gotten 0 back for more than the ir remote send interval 299 | unsigned int zeroTime = 0; 300 | 301 | if (irCode == 0) { 302 | zeroTime = millis() - zeroStartTime; 303 | if (zeroTime >= zeroDelay && lastIrCode != 0) { 304 | //Serial.println(F("zero delay has elapsed, returning last ir code")); 305 | // the button has been released for longer than the zero delay 306 | // start over delays over and return the last code 307 | irCode = lastIrCode; 308 | lastIrCode = 0; 309 | return irCode; 310 | } 311 | 312 | return 0; 313 | } 314 | 315 | // reset the zero timer every time a non-zero code is read 316 | zeroStartTime = millis(); 317 | 318 | unsigned int heldTime = 0; 319 | 320 | if (irCode == IRCODE_SPARKFUN_HELD || irCode == IRCODE_ADAFRUIT_HELD) { 321 | // has the hold delay passed? 322 | heldTime = millis() - holdStartTime; 323 | if (heldTime >= holdDelay) { 324 | isHolding = true; 325 | //Serial.println(F("hold delay has elapsed, returning last ir code")); 326 | return lastIrCode; 327 | } 328 | else if (holdStartTime == 0) { 329 | isHolding = false; 330 | holdStartTime = millis(); 331 | } 332 | } 333 | else { 334 | // not zero, not IRCODE_SPARKFUN_HELD 335 | // store it for use later, until the hold and zero delays have elapsed 336 | holdStartTime = millis(); 337 | isHolding = false; 338 | lastIrCode = irCode; 339 | return 0; 340 | } 341 | 342 | return 0; 343 | } 344 | 345 | void heldButtonHasBeenHandled() { 346 | lastIrCode = 0; 347 | isHolding = false; 348 | holdStartTime = 0; 349 | } 350 | 351 | unsigned long waitForIRCode() { 352 | 353 | unsigned long irCode = readIRCode(); 354 | while ((irCode == 0) || (irCode == 0xFFFFFFFF)) { 355 | delay(200); 356 | irCode = readIRCode(); 357 | } 358 | return irCode; 359 | } 360 | 361 | InputCommand getCommand(unsigned long input) { 362 | if (adafruitRemoteEnabled) { 363 | switch (input) { 364 | case IRCODE_ADAFRUIT_UP: 365 | return InputCommand::Up; 366 | 367 | case IRCODE_ADAFRUIT_DOWN: 368 | return InputCommand::Down; 369 | 370 | case IRCODE_ADAFRUIT_LEFT: 371 | return InputCommand::Left; 372 | 373 | case IRCODE_ADAFRUIT_RIGHT: 374 | return InputCommand::Right; 375 | 376 | case IRCODE_ADAFRUIT_ENTER_SAVE: 377 | return InputCommand::Select; 378 | 379 | case IRCODE_ADAFRUIT_STOP_MODE: 380 | case IRCODE_ADAFRUIT_1: 381 | return InputCommand::PlayMode; 382 | 383 | case IRCODE_ADAFRUIT_2: 384 | return InputCommand::Palette; 385 | 386 | case IRCODE_ADAFRUIT_PLAY_PAUSE: 387 | return InputCommand::Power; 388 | 389 | case IRCODE_ADAFRUIT_VOLUME_UP: 390 | return InputCommand::BrightnessUp; 391 | 392 | case IRCODE_ADAFRUIT_VOLUME_DOWN: 393 | return InputCommand::BrightnessDown; 394 | } 395 | } 396 | 397 | if (sparkfunRemoteEnabled) { 398 | switch (input) { 399 | case IRCODE_SPARKFUN_UP: 400 | return InputCommand::Up; 401 | 402 | case IRCODE_SPARKFUN_DOWN: 403 | return InputCommand::Down; 404 | 405 | case IRCODE_SPARKFUN_LEFT: 406 | return InputCommand::Left; 407 | 408 | case IRCODE_SPARKFUN_RIGHT: 409 | return InputCommand::Right; 410 | 411 | case IRCODE_SPARKFUN_SELECT: 412 | return InputCommand::Select; 413 | 414 | case IRCODE_SPARKFUN_POWER: 415 | return InputCommand::Brightness; 416 | 417 | case IRCODE_SPARKFUN_A: 418 | return InputCommand::PlayMode; 419 | 420 | case IRCODE_SPARKFUN_B: 421 | return InputCommand::Palette; 422 | } 423 | } 424 | 425 | if (etopxizuRemoteEnabled) { 426 | switch (input) { 427 | case IRCODE_ETOPXIZU_QUICK: 428 | return InputCommand::Up; 429 | 430 | case IRCODE_ETOPXIZU_SLOW: 431 | return InputCommand::Down; 432 | 433 | case IRCODE_ETOPXIZU_PLAY_PAUSE: 434 | return InputCommand::PlayMode; 435 | 436 | case IRCODE_ETOPXIZU_POWER: 437 | return InputCommand::Power; 438 | 439 | case IRCODE_ETOPXIZU_BRIGHTNESS_UP: 440 | return InputCommand::BrightnessUp; 441 | case IRCODE_ETOPXIZU_BRIGHTNESS_DOWN: 442 | return InputCommand::BrightnessDown; 443 | 444 | case IRCODE_ETOPXIZU_DIY1: 445 | return InputCommand::Pattern1; 446 | case IRCODE_ETOPXIZU_DIY2: 447 | return InputCommand::Pattern2; 448 | case IRCODE_ETOPXIZU_DIY3: 449 | return InputCommand::Pattern3; 450 | case IRCODE_ETOPXIZU_DIY4: 451 | return InputCommand::Pattern4; 452 | case IRCODE_ETOPXIZU_DIY5: 453 | return InputCommand::Pattern5; 454 | case IRCODE_ETOPXIZU_DIY6: 455 | return InputCommand::Pattern6; 456 | case IRCODE_ETOPXIZU_JUMP3: 457 | return InputCommand::Pattern7; 458 | case IRCODE_ETOPXIZU_JUMP7: 459 | return InputCommand::Pattern8; 460 | case IRCODE_ETOPXIZU_FADE3: 461 | return InputCommand::Pattern9; 462 | case IRCODE_ETOPXIZU_FADE7: 463 | return InputCommand::Pattern10; 464 | case IRCODE_ETOPXIZU_FLASH: 465 | return InputCommand::Pattern11; 466 | case IRCODE_ETOPXIZU_AUTO: 467 | return InputCommand::Pattern12; 468 | 469 | case IRCODE_ETOPXIZU_RED_UP: 470 | return InputCommand::RedUp; 471 | case IRCODE_ETOPXIZU_RED_DOWN: 472 | return InputCommand::RedDown; 473 | 474 | case IRCODE_ETOPXIZU_GREEN_UP: 475 | return InputCommand::GreenUp; 476 | case IRCODE_ETOPXIZU_GREEN_DOWN: 477 | return InputCommand::GreenDown; 478 | 479 | case IRCODE_ETOPXIZU_BLUE_UP: 480 | return InputCommand::BlueUp; 481 | case IRCODE_ETOPXIZU_BLUE_DOWN: 482 | return InputCommand::BlueDown; 483 | 484 | case IRCODE_ETOPXIZU_RED: 485 | return InputCommand::Red; 486 | case IRCODE_ETOPXIZU_RED_ORANGE: 487 | return InputCommand::RedOrange; 488 | case IRCODE_ETOPXIZU_ORANGE: 489 | return InputCommand::Orange; 490 | case IRCODE_ETOPXIZU_YELLOW_ORANGE: 491 | return InputCommand::YellowOrange; 492 | case IRCODE_ETOPXIZU_YELLOW: 493 | return InputCommand::Yellow; 494 | 495 | case IRCODE_ETOPXIZU_GREEN: 496 | return InputCommand::Green; 497 | case IRCODE_ETOPXIZU_LIME: 498 | return InputCommand::Lime; 499 | case IRCODE_ETOPXIZU_AQUA: 500 | return InputCommand::Aqua; 501 | case IRCODE_ETOPXIZU_TEAL: 502 | return InputCommand::Teal; 503 | case IRCODE_ETOPXIZU_NAVY: 504 | return InputCommand::Navy; 505 | 506 | case IRCODE_ETOPXIZU_BLUE: 507 | return InputCommand::Blue; 508 | case IRCODE_ETOPXIZU_ROYAL_BLUE: 509 | return InputCommand::RoyalBlue; 510 | case IRCODE_ETOPXIZU_PURPLE: 511 | return InputCommand::Purple; 512 | case IRCODE_ETOPXIZU_INDIGO: 513 | return InputCommand::Indigo; 514 | case IRCODE_ETOPXIZU_MAGENTA: 515 | return InputCommand::Magenta; 516 | 517 | case IRCODE_ETOPXIZU_WHITE: 518 | return InputCommand::White; 519 | case IRCODE_ETOPXIZU_PINK: 520 | return InputCommand::Pink; 521 | case IRCODE_ETOPXIZU_LIGHT_PINK: 522 | return InputCommand::LightPink; 523 | case IRCODE_ETOPXIZU_BABY_BLUE: 524 | return InputCommand::BabyBlue; 525 | case IRCODE_ETOPXIZU_LIGHT_BLUE: 526 | return InputCommand::LightBlue; 527 | } 528 | } 529 | 530 | return InputCommand::None; 531 | } 532 | 533 | InputCommand readCommand() { 534 | return getCommand(readIRCode()); 535 | } 536 | 537 | InputCommand readCommand(unsigned int holdDelay) { 538 | return getCommand(readIRCode(holdDelay)); 539 | } 540 | 541 | #endif 542 | -------------------------------------------------------------------------------- /GradientPalettes.h: -------------------------------------------------------------------------------- 1 | // From ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb 2 | 3 | // Gradient Color Palette definitions for 33 different cpt-city color palettes. 4 | // 956 bytes of PROGMEM for all of the palettes together, 5 | // +618 bytes of PROGMEM for gradient palette code (AVR). 6 | // 1,494 bytes total for all 34 color palettes and associated code. 7 | 8 | // Gradient palette "ib_jul01_gp", originally from 9 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/xmas/tn/ib_jul01.png.index.html 10 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 11 | // Size: 16 bytes of program space. 12 | 13 | DEFINE_GRADIENT_PALETTE( ib_jul01_gp ) { 14 | 0, 194, 1, 1, 15 | 94, 1, 29, 18, 16 | 132, 57,131, 28, 17 | 255, 113, 1, 1}; 18 | 19 | // Gradient palette "es_vintage_57_gp", originally from 20 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/vintage/tn/es_vintage_57.png.index.html 21 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 22 | // Size: 20 bytes of program space. 23 | 24 | DEFINE_GRADIENT_PALETTE( es_vintage_57_gp ) { 25 | 0, 2, 1, 1, 26 | 53, 18, 1, 0, 27 | 104, 69, 29, 1, 28 | 153, 167,135, 10, 29 | 255, 46, 56, 4}; 30 | 31 | // Gradient palette "es_vintage_01_gp", originally from 32 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/vintage/tn/es_vintage_01.png.index.html 33 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 34 | // Size: 32 bytes of program space. 35 | 36 | DEFINE_GRADIENT_PALETTE( es_vintage_01_gp ) { 37 | 0, 4, 1, 1, 38 | 51, 16, 0, 1, 39 | 76, 97,104, 3, 40 | 101, 255,131, 19, 41 | 127, 67, 9, 4, 42 | 153, 16, 0, 1, 43 | 229, 4, 1, 1, 44 | 255, 4, 1, 1}; 45 | 46 | // Gradient palette "es_rivendell_15_gp", originally from 47 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/rivendell/tn/es_rivendell_15.png.index.html 48 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 49 | // Size: 20 bytes of program space. 50 | 51 | DEFINE_GRADIENT_PALETTE( es_rivendell_15_gp ) { 52 | 0, 1, 14, 5, 53 | 101, 16, 36, 14, 54 | 165, 56, 68, 30, 55 | 242, 150,156, 99, 56 | 255, 150,156, 99}; 57 | 58 | // Gradient palette "rgi_15_gp", originally from 59 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ds/rgi/tn/rgi_15.png.index.html 60 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 61 | // Size: 36 bytes of program space. 62 | 63 | DEFINE_GRADIENT_PALETTE( rgi_15_gp ) { 64 | 0, 4, 1, 31, 65 | 31, 55, 1, 16, 66 | 63, 197, 3, 7, 67 | 95, 59, 2, 17, 68 | 127, 6, 2, 34, 69 | 159, 39, 6, 33, 70 | 191, 112, 13, 32, 71 | 223, 56, 9, 35, 72 | 255, 22, 6, 38}; 73 | 74 | // Gradient palette "retro2_16_gp", originally from 75 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ma/retro2/tn/retro2_16.png.index.html 76 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 77 | // Size: 8 bytes of program space. 78 | 79 | DEFINE_GRADIENT_PALETTE( retro2_16_gp ) { 80 | 0, 188,135, 1, 81 | 255, 46, 7, 1}; 82 | 83 | // Gradient palette "Analogous_1_gp", originally from 84 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/red/tn/Analogous_1.png.index.html 85 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 86 | // Size: 20 bytes of program space. 87 | 88 | DEFINE_GRADIENT_PALETTE( Analogous_1_gp ) { 89 | 0, 3, 0,255, 90 | 63, 23, 0,255, 91 | 127, 67, 0,255, 92 | 191, 142, 0, 45, 93 | 255, 255, 0, 0}; 94 | 95 | // Gradient palette "es_pinksplash_08_gp", originally from 96 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/pink_splash/tn/es_pinksplash_08.png.index.html 97 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 98 | // Size: 20 bytes of program space. 99 | 100 | DEFINE_GRADIENT_PALETTE( es_pinksplash_08_gp ) { 101 | 0, 126, 11,255, 102 | 127, 197, 1, 22, 103 | 175, 210,157,172, 104 | 221, 157, 3,112, 105 | 255, 157, 3,112}; 106 | 107 | // Gradient palette "es_pinksplash_07_gp", originally from 108 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/pink_splash/tn/es_pinksplash_07.png.index.html 109 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 110 | // Size: 28 bytes of program space. 111 | 112 | DEFINE_GRADIENT_PALETTE( es_pinksplash_07_gp ) { 113 | 0, 229, 1, 1, 114 | 61, 242, 4, 63, 115 | 101, 255, 12,255, 116 | 127, 249, 81,252, 117 | 153, 255, 11,235, 118 | 193, 244, 5, 68, 119 | 255, 232, 1, 5}; 120 | 121 | // Gradient palette "Coral_reef_gp", originally from 122 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/other/tn/Coral_reef.png.index.html 123 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 124 | // Size: 24 bytes of program space. 125 | 126 | DEFINE_GRADIENT_PALETTE( Coral_reef_gp ) { 127 | 0, 40,199,197, 128 | 50, 10,152,155, 129 | 96, 1,111,120, 130 | 96, 43,127,162, 131 | 139, 10, 73,111, 132 | 255, 1, 34, 71}; 133 | 134 | // Gradient palette "es_ocean_breeze_068_gp", originally from 135 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/ocean_breeze/tn/es_ocean_breeze_068.png.index.html 136 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 137 | // Size: 24 bytes of program space. 138 | 139 | DEFINE_GRADIENT_PALETTE( es_ocean_breeze_068_gp ) { 140 | 0, 100,156,153, 141 | 51, 1, 99,137, 142 | 101, 1, 68, 84, 143 | 104, 35,142,168, 144 | 178, 0, 63,117, 145 | 255, 1, 10, 10}; 146 | 147 | // Gradient palette "es_ocean_breeze_036_gp", originally from 148 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/ocean_breeze/tn/es_ocean_breeze_036.png.index.html 149 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 150 | // Size: 16 bytes of program space. 151 | 152 | DEFINE_GRADIENT_PALETTE( es_ocean_breeze_036_gp ) { 153 | 0, 1, 6, 7, 154 | 89, 1, 99,111, 155 | 153, 144,209,255, 156 | 255, 0, 73, 82}; 157 | 158 | // Gradient palette "departure_gp", originally from 159 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/mjf/tn/departure.png.index.html 160 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 161 | // Size: 88 bytes of program space. 162 | 163 | DEFINE_GRADIENT_PALETTE( departure_gp ) { 164 | 0, 8, 3, 0, 165 | 42, 23, 7, 0, 166 | 63, 75, 38, 6, 167 | 84, 169, 99, 38, 168 | 106, 213,169,119, 169 | 116, 255,255,255, 170 | 138, 135,255,138, 171 | 148, 22,255, 24, 172 | 170, 0,255, 0, 173 | 191, 0,136, 0, 174 | 212, 0, 55, 0, 175 | 255, 0, 55, 0}; 176 | 177 | // Gradient palette "es_landscape_64_gp", originally from 178 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/landscape/tn/es_landscape_64.png.index.html 179 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 180 | // Size: 36 bytes of program space. 181 | 182 | DEFINE_GRADIENT_PALETTE( es_landscape_64_gp ) { 183 | 0, 0, 0, 0, 184 | 37, 2, 25, 1, 185 | 76, 15,115, 5, 186 | 127, 79,213, 1, 187 | 128, 126,211, 47, 188 | 130, 188,209,247, 189 | 153, 144,182,205, 190 | 204, 59,117,250, 191 | 255, 1, 37,192}; 192 | 193 | // Gradient palette "es_landscape_33_gp", originally from 194 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/landscape/tn/es_landscape_33.png.index.html 195 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 196 | // Size: 24 bytes of program space. 197 | 198 | DEFINE_GRADIENT_PALETTE( es_landscape_33_gp ) { 199 | 0, 1, 5, 0, 200 | 19, 32, 23, 1, 201 | 38, 161, 55, 1, 202 | 63, 229,144, 1, 203 | 66, 39,142, 74, 204 | 255, 1, 4, 1}; 205 | 206 | // Gradient palette "rainbowsherbet_gp", originally from 207 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ma/icecream/tn/rainbowsherbet.png.index.html 208 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 209 | // Size: 28 bytes of program space. 210 | 211 | DEFINE_GRADIENT_PALETTE( rainbowsherbet_gp ) { 212 | 0, 255, 33, 4, 213 | 43, 255, 68, 25, 214 | 86, 255, 7, 25, 215 | 127, 255, 82,103, 216 | 170, 255,255,242, 217 | 209, 42,255, 22, 218 | 255, 87,255, 65}; 219 | 220 | // Gradient palette "gr65_hult_gp", originally from 221 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/hult/tn/gr65_hult.png.index.html 222 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 223 | // Size: 24 bytes of program space. 224 | 225 | DEFINE_GRADIENT_PALETTE( gr65_hult_gp ) { 226 | 0, 247,176,247, 227 | 48, 255,136,255, 228 | 89, 220, 29,226, 229 | 160, 7, 82,178, 230 | 216, 1,124,109, 231 | 255, 1,124,109}; 232 | 233 | // Gradient palette "gr64_hult_gp", originally from 234 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/hult/tn/gr64_hult.png.index.html 235 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 236 | // Size: 32 bytes of program space. 237 | 238 | DEFINE_GRADIENT_PALETTE( gr64_hult_gp ) { 239 | 0, 1,124,109, 240 | 66, 1, 93, 79, 241 | 104, 52, 65, 1, 242 | 130, 115,127, 1, 243 | 150, 52, 65, 1, 244 | 201, 1, 86, 72, 245 | 239, 0, 55, 45, 246 | 255, 0, 55, 45}; 247 | 248 | // Gradient palette "GMT_drywet_gp", originally from 249 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/gmt/tn/GMT_drywet.png.index.html 250 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 251 | // Size: 28 bytes of program space. 252 | 253 | DEFINE_GRADIENT_PALETTE( GMT_drywet_gp ) { 254 | 0, 47, 30, 2, 255 | 42, 213,147, 24, 256 | 84, 103,219, 52, 257 | 127, 3,219,207, 258 | 170, 1, 48,214, 259 | 212, 1, 1,111, 260 | 255, 1, 7, 33}; 261 | 262 | // Gradient palette "ib15_gp", originally from 263 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ing/general/tn/ib15.png.index.html 264 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 265 | // Size: 24 bytes of program space. 266 | 267 | DEFINE_GRADIENT_PALETTE( ib15_gp ) { 268 | 0, 113, 91,147, 269 | 72, 157, 88, 78, 270 | 89, 208, 85, 33, 271 | 107, 255, 29, 11, 272 | 141, 137, 31, 39, 273 | 255, 59, 33, 89}; 274 | 275 | // Gradient palette "Fuschia_7_gp", originally from 276 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/ds/fuschia/tn/Fuschia-7.png.index.html 277 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 278 | // Size: 20 bytes of program space. 279 | 280 | DEFINE_GRADIENT_PALETTE( Fuschia_7_gp ) { 281 | 0, 43, 3,153, 282 | 63, 100, 4,103, 283 | 127, 188, 5, 66, 284 | 191, 161, 11,115, 285 | 255, 135, 20,182}; 286 | 287 | // Gradient palette "es_emerald_dragon_08_gp", originally from 288 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/emerald_dragon/tn/es_emerald_dragon_08.png.index.html 289 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 290 | // Size: 16 bytes of program space. 291 | 292 | DEFINE_GRADIENT_PALETTE( es_emerald_dragon_08_gp ) { 293 | 0, 97,255, 1, 294 | 101, 47,133, 1, 295 | 178, 13, 43, 1, 296 | 255, 2, 10, 1}; 297 | 298 | // Gradient palette "lava_gp", originally from 299 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/neota/elem/tn/lava.png.index.html 300 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 301 | // Size: 52 bytes of program space. 302 | 303 | DEFINE_GRADIENT_PALETTE( lava_gp ) { 304 | 0, 0, 0, 0, 305 | 46, 18, 0, 0, 306 | 96, 113, 0, 0, 307 | 108, 142, 3, 1, 308 | 119, 175, 17, 1, 309 | 146, 213, 44, 2, 310 | 174, 255, 82, 4, 311 | 188, 255,115, 4, 312 | 202, 255,156, 4, 313 | 218, 255,203, 4, 314 | 234, 255,255, 4, 315 | 244, 255,255, 71, 316 | 255, 255,255,255}; 317 | 318 | // Gradient palette "fire_gp", originally from 319 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/neota/elem/tn/fire.png.index.html 320 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 321 | // Size: 28 bytes of program space. 322 | 323 | DEFINE_GRADIENT_PALETTE( fire_gp ) { 324 | 0, 1, 1, 0, 325 | 76, 32, 5, 0, 326 | 146, 192, 24, 0, 327 | 197, 220,105, 5, 328 | 240, 252,255, 31, 329 | 250, 252,255,111, 330 | 255, 255,255,255}; 331 | 332 | // Gradient palette "Colorfull_gp", originally from 333 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Colorfull.png.index.html 334 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 335 | // Size: 44 bytes of program space. 336 | 337 | DEFINE_GRADIENT_PALETTE( Colorfull_gp ) { 338 | 0, 10, 85, 5, 339 | 25, 29,109, 18, 340 | 60, 59,138, 42, 341 | 93, 83, 99, 52, 342 | 106, 110, 66, 64, 343 | 109, 123, 49, 65, 344 | 113, 139, 35, 66, 345 | 116, 192,117, 98, 346 | 124, 255,255,137, 347 | 168, 100,180,155, 348 | 255, 22,121,174}; 349 | 350 | // Gradient palette "Magenta_Evening_gp", originally from 351 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Magenta_Evening.png.index.html 352 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 353 | // Size: 28 bytes of program space. 354 | 355 | DEFINE_GRADIENT_PALETTE( Magenta_Evening_gp ) { 356 | 0, 71, 27, 39, 357 | 31, 130, 11, 51, 358 | 63, 213, 2, 64, 359 | 70, 232, 1, 66, 360 | 76, 252, 1, 69, 361 | 108, 123, 2, 51, 362 | 255, 46, 9, 35}; 363 | 364 | // Gradient palette "Pink_Purple_gp", originally from 365 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Pink_Purple.png.index.html 366 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 367 | // Size: 44 bytes of program space. 368 | 369 | DEFINE_GRADIENT_PALETTE( Pink_Purple_gp ) { 370 | 0, 19, 2, 39, 371 | 25, 26, 4, 45, 372 | 51, 33, 6, 52, 373 | 76, 68, 62,125, 374 | 102, 118,187,240, 375 | 109, 163,215,247, 376 | 114, 217,244,255, 377 | 122, 159,149,221, 378 | 149, 113, 78,188, 379 | 183, 128, 57,155, 380 | 255, 146, 40,123}; 381 | 382 | // Gradient palette "Sunset_Real_gp", originally from 383 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/atmospheric/tn/Sunset_Real.png.index.html 384 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 385 | // Size: 28 bytes of program space. 386 | 387 | DEFINE_GRADIENT_PALETTE( Sunset_Real_gp ) { 388 | 0, 120, 0, 0, 389 | 22, 179, 22, 0, 390 | 51, 255,104, 0, 391 | 85, 167, 22, 18, 392 | 135, 100, 0,103, 393 | 198, 16, 0,130, 394 | 255, 0, 0,160}; 395 | 396 | // Gradient palette "es_autumn_19_gp", originally from 397 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/autumn/tn/es_autumn_19.png.index.html 398 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 399 | // Size: 52 bytes of program space. 400 | 401 | DEFINE_GRADIENT_PALETTE( es_autumn_19_gp ) { 402 | 0, 26, 1, 1, 403 | 51, 67, 4, 1, 404 | 84, 118, 14, 1, 405 | 104, 137,152, 52, 406 | 112, 113, 65, 1, 407 | 122, 133,149, 59, 408 | 124, 137,152, 52, 409 | 135, 113, 65, 1, 410 | 142, 139,154, 46, 411 | 163, 113, 13, 1, 412 | 204, 55, 3, 1, 413 | 249, 17, 1, 1, 414 | 255, 17, 1, 1}; 415 | 416 | // Gradient palette "BlacK_Blue_Magenta_White_gp", originally from 417 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Blue_Magenta_White.png.index.html 418 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 419 | // Size: 28 bytes of program space. 420 | 421 | DEFINE_GRADIENT_PALETTE( BlacK_Blue_Magenta_White_gp ) { 422 | 0, 0, 0, 0, 423 | 42, 0, 0, 45, 424 | 84, 0, 0,255, 425 | 127, 42, 0,255, 426 | 170, 255, 0,255, 427 | 212, 255, 55,255, 428 | 255, 255,255,255}; 429 | 430 | // Gradient palette "BlacK_Magenta_Red_gp", originally from 431 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Magenta_Red.png.index.html 432 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 433 | // Size: 20 bytes of program space. 434 | 435 | DEFINE_GRADIENT_PALETTE( BlacK_Magenta_Red_gp ) { 436 | 0, 0, 0, 0, 437 | 63, 42, 0, 45, 438 | 127, 255, 0,255, 439 | 191, 255, 0, 45, 440 | 255, 255, 0, 0}; 441 | 442 | // Gradient palette "BlacK_Red_Magenta_Yellow_gp", originally from 443 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/BlacK_Red_Magenta_Yellow.png.index.html 444 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 445 | // Size: 28 bytes of program space. 446 | 447 | DEFINE_GRADIENT_PALETTE( BlacK_Red_Magenta_Yellow_gp ) { 448 | 0, 0, 0, 0, 449 | 42, 42, 0, 0, 450 | 84, 255, 0, 0, 451 | 127, 255, 0, 45, 452 | 170, 255, 0,255, 453 | 212, 255, 55, 45, 454 | 255, 255,255, 0}; 455 | 456 | // Gradient palette "Blue_Cyan_Yellow_gp", originally from 457 | // http://soliton.vm.bytemark.co.uk/pub/cpt-city/nd/basic/tn/Blue_Cyan_Yellow.png.index.html 458 | // converted for FastLED with gammas (2.6, 2.2, 2.5) 459 | // Size: 20 bytes of program space. 460 | 461 | DEFINE_GRADIENT_PALETTE( Blue_Cyan_Yellow_gp ) { 462 | 0, 0, 0,255, 463 | 63, 0, 55,255, 464 | 127, 0,255,255, 465 | 191, 42,255, 45, 466 | 255, 255,255, 0}; 467 | 468 | 469 | // Single array of defined cpt-city color palettes. 470 | // This will let us programmatically choose one based on 471 | // a number, rather than having to activate each explicitly 472 | // by name every time. 473 | // Since it is const, this array could also be moved 474 | // into PROGMEM to save SRAM, but for simplicity of illustration 475 | // we'll keep it in a regular SRAM array. 476 | // 477 | // This list of color palettes acts as a "playlist"; you can 478 | // add or delete, or re-arrange as you wish. 479 | const TProgmemRGBGradientPalettePtr gGradientPalettes[] = { 480 | Sunset_Real_gp, 481 | es_rivendell_15_gp, 482 | es_ocean_breeze_036_gp, 483 | rgi_15_gp, 484 | retro2_16_gp, 485 | Analogous_1_gp, 486 | es_pinksplash_08_gp, 487 | Coral_reef_gp, 488 | es_ocean_breeze_068_gp, 489 | es_pinksplash_07_gp, 490 | es_vintage_01_gp, 491 | departure_gp, 492 | es_landscape_64_gp, 493 | es_landscape_33_gp, 494 | rainbowsherbet_gp, 495 | gr65_hult_gp, 496 | gr64_hult_gp, 497 | GMT_drywet_gp, 498 | ib_jul01_gp, 499 | es_vintage_57_gp, 500 | ib15_gp, 501 | Fuschia_7_gp, 502 | es_emerald_dragon_08_gp, 503 | lava_gp, 504 | fire_gp, 505 | Colorfull_gp, 506 | Magenta_Evening_gp, 507 | Pink_Purple_gp, 508 | es_autumn_19_gp, 509 | BlacK_Blue_Magenta_White_gp, 510 | BlacK_Magenta_Red_gp, 511 | BlacK_Red_Magenta_Yellow_gp, 512 | Blue_Cyan_Yellow_gp }; 513 | 514 | 515 | // Count of how many cpt-city gradients are defined: 516 | const uint8_t gGradientPaletteCount = 517 | sizeof( gGradientPalettes) / sizeof( TProgmemRGBGradientPalettePtr ); 518 | 519 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Life.h: -------------------------------------------------------------------------------- 1 | /* 2 | Fibonacci v3D: https://github.com/evilgeniuslabs/fibonacci-v3d 3 | Copyright (C) 2014-2016 Jason Coon, Evil Genius Labs 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | class Cell 20 | { 21 | public: 22 | byte alive = 1; 23 | byte prev = 1; 24 | byte hue = 6; 25 | byte brightness; 26 | }; 27 | 28 | Cell world[kMatrixWidth][kMatrixHeight]; 29 | 30 | uint8_t neighbors(uint8_t x, uint8_t y) 31 | { 32 | return (world[(x + 1) % kMatrixWidth][y].prev) + 33 | (world[x][(y + 1) % kMatrixHeight].prev) + 34 | (world[(x + kMatrixWidth - 1) % kMatrixWidth][y].prev) + 35 | (world[x][(y + kMatrixHeight - 1) % kMatrixHeight].prev) + 36 | (world[(x + 1) % kMatrixWidth][(y + 1) % kMatrixHeight].prev) + 37 | (world[(x + kMatrixWidth - 1) % kMatrixWidth][(y + 1) % kMatrixHeight].prev) + 38 | (world[(x + kMatrixWidth - 1) % kMatrixWidth][(y + kMatrixHeight - 1) % kMatrixHeight].prev) + 39 | (world[(x + 1) % kMatrixWidth][(y + kMatrixHeight - 1) % kMatrixHeight].prev); 40 | } 41 | 42 | void randomFillWorld() 43 | { 44 | static uint8_t lifeDensity = 10; 45 | 46 | for (uint8_t i = 0; i < kMatrixWidth; i++) { 47 | for (uint8_t j = 0; j < kMatrixHeight; j++) { 48 | if (random(100) < lifeDensity) { 49 | world[i][j].alive = 1; 50 | world[i][j].brightness = 255; 51 | } 52 | else { 53 | world[i][j].alive = 0; 54 | world[i][j].brightness = 0; 55 | } 56 | world[i][j].prev = world[i][j].alive; 57 | world[i][j].hue = 0; 58 | } 59 | } 60 | } 61 | 62 | uint8_t life() 63 | { 64 | static uint8_t generation = 0; 65 | 66 | // Display current generation 67 | for (uint8_t i = 0; i < kMatrixWidth; i++) 68 | { 69 | for (uint8_t j = 0; j < kMatrixHeight; j++) 70 | { 71 | setPixelXY(i, j, ColorFromPalette(currentPalette, world[i][j].hue * 4, world[i][j].brightness, LINEARBLEND)); 72 | } 73 | } 74 | 75 | uint8_t liveCells = 0; 76 | 77 | // Birth and death cycle 78 | for (uint8_t x = 0; x < kMatrixWidth; x++) 79 | { 80 | for (uint8_t y = 0; y < kMatrixHeight; y++) 81 | { 82 | // Default is for cell to stay the same 83 | if (world[x][y].brightness > 0 && world[x][y].prev == 0) 84 | world[x][y].brightness *= 0.5; 85 | 86 | uint8_t count = neighbors(x, y); 87 | 88 | if (count == 3 && world[x][y].prev == 0) 89 | { 90 | // A new cell is born 91 | world[x][y].alive = 1; 92 | world[x][y].hue += 2; 93 | world[x][y].brightness = 255; 94 | } 95 | else if ((count < 2 || count > 3) && world[x][y].prev == 1) 96 | { 97 | // Cell dies 98 | world[x][y].alive = 0; 99 | } 100 | 101 | if (world[x][y].alive) 102 | liveCells++; 103 | } 104 | } 105 | 106 | // Copy next generation into place 107 | for (uint8_t x = 0; x < kMatrixWidth; x++) 108 | { 109 | for (uint8_t y = 0; y < kMatrixHeight; y++) 110 | { 111 | world[x][y].prev = world[x][y].alive; 112 | } 113 | } 114 | 115 | if (liveCells < 4 || generation >= 128) 116 | { 117 | fill_solid(leds, NUM_LEDS, CRGB::Black); 118 | 119 | randomFillWorld(); 120 | 121 | generation = 0; 122 | } 123 | else 124 | { 125 | generation++; 126 | } 127 | 128 | return 60; 129 | } 130 | 131 | -------------------------------------------------------------------------------- /Noise.h: -------------------------------------------------------------------------------- 1 | /* 2 | Fibonacci v3D: https://github.com/evilgeniuslabs/fibonacci-v3d 3 | Copyright (C) 2014-2016 Jason Coon, Evil Genius Labs 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | #define MATRIX_WIDTH 32 19 | #define MATRIX_HEIGHT 32 20 | 21 | #define MAX_DIMENSION ((MATRIX_WIDTH > MATRIX_HEIGHT) ? MATRIX_WIDTH : MATRIX_HEIGHT) 22 | 23 | // The 16 bit version of our coordinates 24 | uint16_t noisex; 25 | uint16_t noisey; 26 | uint16_t noisez; 27 | 28 | // We're using the x/y dimensions to map to the x/y pixels on the matrix. We'll 29 | // use the z-axis for "time". speed determines how fast time moves forward. Try 30 | // 1 for a very slow moving effect, or 60 for something that ends up looking like 31 | // water. 32 | int noisespeedx = 0; 33 | int noisespeedy = 1; 34 | int noisespeedz = 0; 35 | 36 | // Scale determines how far apart the pixels in our noise matrix are. Try 37 | // changing these values around to see how it affects the motion of the display. The 38 | // higher the value of scale, the more "zoomed out" the noise will be. A value 39 | // of 1 will be so zoomed in, you'll mostly see solid colors. 40 | uint16_t noisescale = 1; // scale is set dynamically once we've started up 41 | 42 | // This is the array that we keep our computed noise values in 43 | uint8_t noise[MAX_DIMENSION][MAX_DIMENSION]; 44 | 45 | uint8_t colorLoop = 0; 46 | 47 | CRGBPalette16 blackAndWhiteStripedPalette; 48 | 49 | // This function sets up a palette of black and white stripes, 50 | // using code. Since the palette is effectively an array of 51 | // sixteen CRGB colors, the various fill_* functions can be used 52 | // to set them up. 53 | void SetupBlackAndWhiteStripedPalette() 54 | { 55 | // 'black out' all 16 palette entries... 56 | fill_solid( blackAndWhiteStripedPalette, 16, CRGB::Black); 57 | // and set every fourth one to white. 58 | blackAndWhiteStripedPalette[0] = CRGB::White; 59 | blackAndWhiteStripedPalette[4] = CRGB::White; 60 | blackAndWhiteStripedPalette[8] = CRGB::White; 61 | blackAndWhiteStripedPalette[12] = CRGB::White; 62 | 63 | } 64 | 65 | CRGBPalette16 blackAndBlueStripedPalette; 66 | 67 | // This function sets up a palette of black and blue stripes, 68 | // using code. Since the palette is effectively an array of 69 | // sixteen CRGB colors, the various fill_* functions can be used 70 | // to set them up. 71 | void SetupBlackAndBlueStripedPalette() 72 | { 73 | // 'black out' all 16 palette entries... 74 | fill_solid( blackAndBlueStripedPalette, 16, CRGB::Black); 75 | 76 | for(uint8_t i = 0; i < 6; i++) { 77 | blackAndBlueStripedPalette[i] = CRGB::Blue; 78 | } 79 | } 80 | 81 | // There are several different palettes of colors demonstrated here. 82 | // 83 | // FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p, 84 | // OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p. 85 | // 86 | // Additionally, you can manually define your own color palettes, or you can write 87 | // code that creates color palettes on the fly. 88 | 89 | uint8_t drawNoise(CRGBPalette16 palette, uint8_t hueReduce = 0) 90 | { 91 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 92 | uint8_t j = physicalToFibonacciOrder[i]; 93 | 94 | uint8_t x = coordsX[j]; 95 | uint8_t y = coordsY[j]; 96 | 97 | int xoffset = noisescale * x; 98 | int yoffset = noisescale * y; 99 | 100 | uint8_t data = inoise8(x + xoffset + noisex, y + yoffset + noisey, noisez); 101 | 102 | // The range of the inoise8 function is roughly 16-238. 103 | // These two operations expand those values out to roughly 0..255 104 | // You can comment them out if you want the raw noise data. 105 | data = qsub8(data, 16); 106 | data = qadd8(data, scale8(data, 39)); 107 | 108 | leds[i] = ColorFromPalette(palette, data, 255, LINEARBLEND); 109 | } 110 | 111 | noisex += noisespeedx; 112 | noisey += noisespeedy; 113 | noisez += noisespeedz; 114 | 115 | return 8; 116 | } 117 | 118 | uint8_t rainbowNoise() { 119 | noisespeedx = 0; 120 | noisespeedy = 2; 121 | noisespeedz = 0; 122 | noisescale = 0; 123 | colorLoop = 0; 124 | return drawNoise(RainbowColors_p); 125 | } 126 | 127 | uint8_t rainbowStripeNoise() { 128 | noisespeedx = 0; 129 | noisespeedy = 2; 130 | noisespeedz = 0; 131 | noisescale = 0; 132 | colorLoop = 0; 133 | return drawNoise(RainbowStripeColors_p); 134 | } 135 | 136 | uint8_t partyNoise() { 137 | noisespeedx = 9; 138 | noisespeedy = 0; 139 | noisespeedz = 0; 140 | noisescale = 1; 141 | colorLoop = 0; 142 | return drawNoise(PartyColors_p); 143 | } 144 | 145 | uint8_t forestNoise() { 146 | noisespeedx = 9; 147 | noisespeedy = 0; 148 | noisespeedz = 0; 149 | noisescale = 1; 150 | colorLoop = 0; 151 | return drawNoise(ForestColors_p); 152 | } 153 | 154 | uint8_t cloudNoise() { 155 | noisespeedx = 2; 156 | noisespeedy = 0; 157 | noisespeedz = 0; 158 | noisescale = 0; 159 | colorLoop = 0; 160 | return drawNoise(CloudColors_p); 161 | } 162 | 163 | uint8_t fireNoise() { 164 | noisespeedx = 0; // 24; 165 | noisespeedy = 64; 166 | noisespeedz = 0; 167 | noisescale = 4; 168 | colorLoop = 0; 169 | return drawNoise(HeatColors_p, 60); 170 | } 171 | 172 | uint8_t fireNoise2() { 173 | noisespeedx = 0; 174 | noisespeedy = 8; 175 | noisespeedz = 4; 176 | noisescale = 1; 177 | colorLoop = 0; 178 | return drawNoise(HeatColors_p); 179 | } 180 | 181 | uint8_t lavaNoise() { 182 | noisespeedx = 0; 183 | noisespeedy = -1; 184 | noisespeedz = 2; 185 | noisescale = 0; 186 | colorLoop = 0; 187 | return drawNoise(LavaColors_p); 188 | } 189 | 190 | uint8_t oceanNoise() { 191 | noisespeedx = 2; 192 | noisespeedy = 0; 193 | noisespeedz = 4; 194 | noisescale = 0; 195 | colorLoop = 0; 196 | return drawNoise(OceanColors_p); 197 | } 198 | 199 | uint8_t blackAndWhiteNoise() { 200 | SetupBlackAndWhiteStripedPalette(); 201 | noisespeedx = 12; 202 | noisespeedy = 0; 203 | noisespeedz = 0; 204 | noisescale = 0; 205 | colorLoop = 0; 206 | return drawNoise(blackAndWhiteStripedPalette); 207 | } 208 | 209 | uint8_t blackAndBlueNoise() { 210 | SetupBlackAndBlueStripedPalette(); 211 | noisespeedx = 0; 212 | noisespeedy = -8; 213 | noisespeedz = 0; 214 | noisescale = 1; 215 | colorLoop = 0; 216 | return drawNoise(blackAndBlueStripedPalette); 217 | } 218 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fibonacci v3D 2 | 3 | [Demo Videos](https://youtu.be/eBLh7yvzN-Y?list=PLUYGVM-2vDxJLjAv6qwl_FOBu8xzAoJL4): 4 | 5 | [![Demo Videos](http://img.youtube.com/vi/eBLh7yvzN-Y/0.jpg)](https://youtu.be/eBLh7yvzN-Y?list=PLUYGVM-2vDxJLjAv6qwl_FOBu8xzAoJL4) 6 | 7 | Built with [100 x WS2811 RGB LEDs](https://www.adafruit.com/products/322), controlled with a [Teensy](https://www.pjrc.com/teensy) using the [FastLED library](https://github.com/FastLED/FastLED). 8 | 9 | Fully open-source, and programmable via a micro USB cable. 10 | 11 | Build your own, or buy one (finished or kit) from [Evil Genius Labs](http://www.evilgeniuslabs.org): http://www.evilgeniuslabs.org 12 | 13 | Controlled via a wireless infrared remote control. 14 | 15 | Build pics, videos, and more details: https://goo.gl/photos/ijtXuzpKviSNW9Kv7 -------------------------------------------------------------------------------- /Twinkles.h: -------------------------------------------------------------------------------- 1 | // based on ColorTwinkles by Mark Kriegsman: https://gist.github.com/kriegsman/5408ecd397744ba0393e 2 | 3 | #define STARTING_BRIGHTNESS 64 4 | #define FADE_IN_SPEED 32 5 | #define FADE_OUT_SPEED 20 6 | #define DENSITY 255 7 | 8 | enum { GETTING_DARKER = 0, GETTING_BRIGHTER = 1 }; 9 | 10 | CRGB makeBrighter( const CRGB& color, fract8 howMuchBrighter) 11 | { 12 | CRGB incrementalColor = color; 13 | incrementalColor.nscale8( howMuchBrighter); 14 | return color + incrementalColor; 15 | } 16 | 17 | CRGB makeDarker( const CRGB& color, fract8 howMuchDarker) 18 | { 19 | CRGB newcolor = color; 20 | newcolor.nscale8( 255 - howMuchDarker); 21 | return newcolor; 22 | } 23 | 24 | // Compact implementation of 25 | // the directionFlags array, using just one BIT of RAM 26 | // per pixel. This requires a bunch of bit wrangling, 27 | // but conserves precious RAM. The cost is a few 28 | // cycles and about 100 bytes of flash program memory. 29 | uint8_t directionFlags[ (NUM_LEDS + 7) / 8]; 30 | 31 | bool getPixelDirection( uint16_t i) 32 | { 33 | uint16_t index = i / 8; 34 | uint8_t bitNum = i & 0x07; 35 | 36 | uint8_t andMask = 1 << bitNum; 37 | return (directionFlags[index] & andMask) != 0; 38 | } 39 | 40 | void setPixelDirection( uint16_t i, bool dir) 41 | { 42 | uint16_t index = i / 8; 43 | uint8_t bitNum = i & 0x07; 44 | 45 | uint8_t orMask = 1 << bitNum; 46 | uint8_t andMask = 255 - orMask; 47 | uint8_t value = directionFlags[index] & andMask; 48 | if ( dir ) { 49 | value += orMask; 50 | } 51 | directionFlags[index] = value; 52 | } 53 | 54 | void brightenOrDarkenEachPixel( fract8 fadeUpAmount, fract8 fadeDownAmount) 55 | { 56 | for ( uint16_t i = 0; i < NUM_LEDS; i++) { 57 | if ( getPixelDirection(i) == GETTING_DARKER) { 58 | // This pixel is getting darker 59 | leds[i] = makeDarker( leds[i], fadeDownAmount); 60 | } else { 61 | // This pixel is getting brighter 62 | leds[i] = makeBrighter( leds[i], fadeUpAmount); 63 | // now check to see if we've maxxed out the brightness 64 | if ( leds[i].r == 255 || leds[i].g == 255 || leds[i].b == 255) { 65 | // if so, turn around and start getting darker 66 | setPixelDirection(i, GETTING_DARKER); 67 | } 68 | } 69 | } 70 | } 71 | 72 | void colortwinkles() 73 | { 74 | // Make each pixel brighter or darker, depending on 75 | // its 'direction' flag. 76 | brightenOrDarkenEachPixel( FADE_IN_SPEED, FADE_OUT_SPEED); 77 | 78 | // Now consider adding a new random twinkle 79 | if ( random8() < DENSITY ) { 80 | int pos = random16(NUM_LEDS); 81 | if ( !leds[pos]) { 82 | leds[pos] = ColorFromPalette( gCurrentPalette, random8(), STARTING_BRIGHTNESS, NOBLEND); 83 | setPixelDirection(pos, GETTING_BRIGHTER); 84 | } 85 | } 86 | } 87 | 88 | uint8_t cloudTwinkles() 89 | { 90 | gCurrentPalette = CloudColors_p; // Blues and whites! 91 | colortwinkles(); 92 | return 20; 93 | } 94 | 95 | uint8_t rainbowTwinkles() 96 | { 97 | gCurrentPalette = RainbowColors_p; 98 | colortwinkles(); 99 | return 20; 100 | } 101 | 102 | uint8_t snowTwinkles() 103 | { 104 | CRGB w(85, 85, 85), W(CRGB::White); 105 | 106 | gCurrentPalette = CRGBPalette16( W, W, W, W, w, w, w, w, w, w, w, w, w, w, w, w ); 107 | colortwinkles(); 108 | return 20; 109 | } 110 | 111 | uint8_t incandescentTwinkles() 112 | { 113 | CRGB l(0xE1A024); 114 | 115 | gCurrentPalette = CRGBPalette16( l, l, l, l, l, l, l, l, l, l, l, l, l, l, l, l ); 116 | colortwinkles(); 117 | return 20; 118 | } 119 | 120 | -------------------------------------------------------------------------------- /fibonacci-v3d.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Fibonacci v3D: https://github.com/evilgeniuslabs/fibonacci-v3d 3 | Copyright (C) 2014-2016 Jason Coon, Evil Genius Labs 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #define IR_RECV_PIN 12 24 | 25 | IRrecv irReceiver(IR_RECV_PIN); 26 | 27 | #include "Commands.h" 28 | #include "GradientPalettes.h" 29 | 30 | #define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0])) 31 | 32 | #define DATA_PIN 0 33 | // #define COLOR_ORDER RGB 34 | #define LED_TYPE WS2811 35 | #define NUM_LEDS 100 36 | 37 | CRGB leds[NUM_LEDS]; 38 | 39 | const uint8_t brightnessCount = 5; 40 | uint8_t brightnessMap[brightnessCount] = { 16, 32, 64, 128, 255 }; 41 | uint8_t brightness = brightnessMap[0]; 42 | 43 | int patternIndex = 0; 44 | CRGB solidColor = CRGB::Red; 45 | 46 | uint8_t gHue = 0; // rotating "base color" used by many of the patterns 47 | 48 | int autoPlayDurationSeconds = 10; 49 | unsigned int autoPlayTimout = 0; 50 | bool autoplayEnabled = false; 51 | 52 | InputCommand command; 53 | 54 | CRGBPalette16 IceColors_p = CRGBPalette16(CRGB::Black, CRGB::Blue, CRGB::Aqua, CRGB::White); 55 | 56 | uint8_t paletteIndex = 0; 57 | 58 | // List of palettes to cycle through. 59 | CRGBPalette16 palettes[] = 60 | { 61 | RainbowColors_p, 62 | RainbowStripeColors_p, 63 | CloudColors_p, 64 | OceanColors_p, 65 | ForestColors_p, 66 | HeatColors_p, 67 | LavaColors_p, 68 | PartyColors_p, 69 | IceColors_p, 70 | }; 71 | 72 | uint8_t paletteCount = ARRAY_SIZE(palettes); 73 | 74 | CRGBPalette16 currentPalette(CRGB::Black); 75 | CRGBPalette16 targetPalette = palettes[paletteIndex]; 76 | 77 | // ten seconds per color palette makes a good demo 78 | // 20-120 is better for deployment 79 | #define SECONDS_PER_PALETTE 10 80 | 81 | /////////////////////////////////////////////////////////////////////// 82 | 83 | // Forward declarations of an array of cpt-city gradient palettes, and 84 | // a count of how many there are. The actual color palette definitions 85 | // are at the bottom of this file. 86 | extern const TProgmemRGBGradientPalettePtr gGradientPalettes[]; 87 | extern const uint8_t gGradientPaletteCount; 88 | 89 | // Current palette number from the 'playlist' of color palettes 90 | uint8_t gCurrentPaletteNumber = 0; 91 | 92 | CRGBPalette16 gCurrentPalette( CRGB::Black); 93 | CRGBPalette16 gTargetPalette( gGradientPalettes[0] ); 94 | 95 | uint8_t fibonacciToPhysicalOrder[100] = { 96 | 99, 97, 98, 96, 92, 95, 91, 93, 89, 84, 97 | 94, 90, 85, 88, 83, 86, 81, 76, 87, 82, 98 | 77, 80, 75, 78, 73, 68, 79, 74, 69, 72, 99 | 67, 70, 65, 60, 71, 66, 61, 64, 59, 62, 100 | 57, 52, 63, 58, 53, 56, 51, 54, 48, 41, 101 | 55, 50, 43, 47, 40, 45, 49, 42, 46, 39, 102 | 44, 36, 28, 33, 38, 30, 35, 27, 32, 37, 103 | 29, 34, 26, 31, 23, 15, 20, 25, 17, 22, 104 | 14, 19, 24, 16, 21, 13, 18, 10, 2, 7, 105 | 12, 4, 9, 1, 6, 11, 3, 8, 0, 5 106 | }; 107 | 108 | uint8_t physicalToFibonacciOrder[100] = { 109 | 98, 93, 88, 96, 91, 99, 94, 89, 97, 92, 110 | 87, 95, 90, 85, 80, 75, 83, 78, 86, 81, 111 | 76, 84, 79, 74, 82, 77, 72, 67, 62, 70, 112 | 65, 73, 68, 63, 71, 66, 61, 69, 64, 59, 113 | 54, 49, 57, 52, 60, 55, 58, 53, 48, 56, 114 | 51, 46, 41, 44, 47, 50, 45, 40, 43, 38, 115 | 33, 36, 39, 42, 37, 32, 35, 30, 25, 28, 116 | 31, 34, 29, 24, 27, 22, 17, 20, 23, 26, 117 | 21, 16, 19, 14, 9, 12, 15, 18, 13, 8, 118 | 11, 6, 4, 7, 10, 5, 3, 1, 2, 0 119 | }; 120 | 121 | // Params for width and height 122 | const uint8_t kMatrixWidth = 32; 123 | const uint8_t kMatrixHeight = 32; 124 | 125 | const uint8_t maxX = kMatrixWidth - 1; 126 | const uint8_t maxY = kMatrixHeight - 1; 127 | 128 | const uint8_t coordsX10[NUM_LEDS] = { 5, 4, 5, 5, 4, 5, 4, 4, 6, 3, 5, 5, 3, 6, 4, 4, 6, 3, 6, 4, 3, 7, 3, 5, 6, 2, 7, 4, 4, 7, 2, 6, 5, 2, 7, 3, 5, 6, 2, 7, 4, 3, 7, 2, 6, 6, 2, 8, 3, 4, 7, 1, 7, 5, 2, 8, 2, 5, 6, 1, 8, 3, 3, 8, 1, 6, 5, 1, 8, 2, 4, 7, 1, 7, 4, 2, 8, 1, 6, 6, 1, 8, 3, 3, 8, 0, 7, 5, 1, 9, 1, 5, 7, 0, 8, 3, 2, 9, 0, 6 }; 129 | 130 | const uint8_t coordsY10[NUM_LEDS] = { 5, 4, 5, 4, 5, 5, 3, 6, 4, 4, 6, 3, 5, 5, 3, 6, 3, 4, 6, 2, 6, 4, 3, 7, 3, 5, 5, 2, 7, 3, 4, 7, 2, 6, 5, 3, 7, 2, 5, 6, 2, 7, 4, 3, 7, 2, 6, 5, 2, 8, 3, 4, 7, 1, 7, 4, 2, 8, 2, 5, 6, 1, 8, 3, 3, 8, 1, 7, 5, 2, 8, 2, 5, 7, 1, 8, 4, 2, 8, 1, 6, 6, 1, 8, 2, 4, 8, 0, 7, 5, 1, 9, 1, 5, 7, 0, 8, 3, 3, 9 }; 131 | 132 | const uint8_t coordsX32[NUM_LEDS] = { 17, 15, 16, 18, 13, 19, 15, 14, 20, 11, 18, 18, 11, 22, 12, 15, 21, 9, 21, 16, 11, 23, 10, 18, 20, 8, 24, 13, 13, 24, 7, 21, 18, 9, 25, 9, 16, 23, 6, 24, 14, 10, 26, 6, 20, 20, 6, 27, 10, 14, 25, 4, 24, 16, 8, 28, 7, 18, 23, 4, 27, 12, 11, 28, 4, 22, 19, 5, 29, 8, 15, 26, 2, 26, 15, 8, 30, 4, 20, 23, 2, 30, 10, 12, 29, 1, 25, 18, 4, 31, 5, 17, 26, 0, 29, 12, 8, 31, 1, 22 }; 133 | 134 | const uint8_t coordsY32[NUM_LEDS] = { 16, 15, 19, 14, 17, 18, 12, 20, 14, 14, 21, 11, 19, 17, 11, 22, 12, 16, 21, 9, 22, 15, 12, 24, 9, 18, 20, 8, 24, 12, 14, 24, 7, 22, 17, 9, 26, 9, 17, 22, 6, 25, 13, 11, 26, 6, 21, 19, 6, 27, 9, 15, 25, 4, 25, 15, 8, 28, 6, 19, 22, 4, 28, 11, 12, 28, 3, 23, 18, 5, 30, 7, 16, 25, 2, 27, 13, 8, 30, 3, 21, 21, 3, 30, 8, 13, 28, 1, 26, 16, 5, 31, 4, 18, 25, 1, 30, 11, 9, 31 }; 135 | 136 | const uint8_t coordsX[NUM_LEDS] = { 137, 116, 130, 143, 101, 154, 119, 112, 164, 91, 146, 141, 88, 175, 100, 121, 168, 74, 168, 125, 90, 188, 77, 142, 160, 66, 189, 102, 105, 190, 59, 167, 141, 69, 204, 75, 128, 181, 48, 193, 113, 83, 210, 52, 158, 161, 48, 213, 82, 109, 203, 36, 189, 131, 61, 225, 53, 142, 184, 30, 216, 97, 85, 223, 30, 177, 154, 39, 234, 61, 120, 208, 17, 211, 117, 60, 240, 31, 159, 180, 19, 237, 77, 94, 231, 11, 198, 142, 35, 251, 40, 135, 207, 4, 232, 99, 66, 250, 11, 179 }; 137 | 138 | const uint8_t coordsY[NUM_LEDS] = { 128, 117, 148, 109, 133, 144, 96, 160, 115, 113, 166, 86, 151, 138, 88, 179, 94, 126, 167, 71, 173, 120, 93, 189, 72, 148, 156, 65, 193, 95, 110, 189, 55, 174, 134, 71, 206, 69, 135, 177, 47, 199, 106, 89, 209, 47, 166, 154, 50, 217, 75, 116, 200, 33, 196, 123, 66, 225, 46, 150, 178, 31, 221, 88, 93, 221, 26, 186, 146, 43, 237, 53, 129, 202, 17, 218, 107, 68, 239, 25, 169, 172, 22, 242, 67, 103, 226, 7, 208, 132, 42, 252, 31, 146, 199, 5, 239, 88, 75, 247 }; 139 | 140 | const uint8_t ledAngles[NUM_LEDS] = { 0, 158, 60, 219, 121, 23, 181, 84, 242, 144, 46, 204, 107, 9, 167, 69, 227, 130, 32, 190, 92, 251, 153, 55, 213, 115, 18, 176, 78, 236, 139, 41, 199, 101, 3, 162, 64, 222, 124, 26, 185, 87, 245, 147, 50, 208, 110, 12, 170, 73, 231, 133, 35, 193, 96, 254, 156, 58, 217, 119, 21, 179, 81, 240, 142, 44, 202, 105, 7, 165, 67, 225, 128, 30, 188, 90, 248, 151, 53, 211, 113, 16, 174, 76, 234, 136, 39, 197, 99, 1, 160, 62, 220, 122, 24, 183, 85, 243, 145, 47 }; 141 | 142 | const uint8_t ledRadii[NUM_LEDS] = { 0, 3, 5, 8, 10, 13, 15, 18, 20, 23, 26, 28, 31, 33, 36, 38, 41, 44, 46, 49, 51, 54, 56, 59, 61, 64, 67, 69, 72, 74, 77, 79, 82, 84, 87, 90, 92, 95, 97, 100, 102, 105, 108, 110, 113, 115, 118, 120, 123, 125, 128, 131, 133, 136, 138, 141, 143, 146, 148, 151, 154, 156, 159, 161, 164, 166, 169, 172, 174, 177, 179, 182, 184, 187, 189, 192, 195, 197, 200, 202, 205, 207, 210, 212, 215, 218, 220, 223, 225, 228, 230, 233, 236, 238, 241, 243, 246, 248, 251, 253 }; 143 | 144 | void setPixelA(uint8_t angle, uint8_t dAngle, CRGB color) 145 | { 146 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 147 | uint8_t o = physicalToFibonacciOrder[i]; 148 | 149 | uint8_t ao = ledAngles[o]; 150 | 151 | if (ao <= qadd8(angle, dAngle) && ao >= qsub8(angle, dAngle)) { 152 | leds[i] = color; 153 | } 154 | } 155 | } 156 | 157 | void setPixelAR(uint8_t angle, uint8_t radius, uint8_t dAngle, uint8_t dRadius, CRGB color) 158 | { 159 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 160 | uint8_t o = physicalToFibonacciOrder[i]; 161 | 162 | uint8_t ao = ledAngles[o]; 163 | 164 | if (ao <= qadd8(angle, dAngle) && ao >= qsub8(angle, dAngle)) { 165 | uint8_t ro = ledRadii[o]; 166 | 167 | if (ro <= qadd8(radius, dRadius) && ro >= qsub8(radius, dRadius)) { 168 | leds[i] = color; 169 | } 170 | } 171 | } 172 | } 173 | 174 | void setPixelXY10(uint8_t x, uint8_t y, CRGB color) 175 | { 176 | if ((x >= 10) || (y >= 10)) { 177 | return; 178 | } 179 | 180 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 181 | uint8_t o = physicalToFibonacciOrder[i]; 182 | 183 | if (coordsX10[o] == x && coordsY10[o] == y) { 184 | leds[i] = color; 185 | } 186 | } 187 | } 188 | 189 | void setPixelXY(uint8_t x, uint8_t y, CRGB color) 190 | { 191 | if ((x >= kMatrixWidth) || (y >= kMatrixHeight)) { 192 | return; 193 | } 194 | 195 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 196 | uint8_t o = physicalToFibonacciOrder[i]; 197 | 198 | if (coordsX32[o] == x && coordsY32[o] == y) { 199 | leds[i] = color; 200 | return; 201 | } 202 | } 203 | } 204 | 205 | void powerOff() 206 | { 207 | // clear the display 208 | // fill_solid(leds, NUM_LEDS, CRGB::Black); 209 | for (int i = 0; i < NUM_LEDS; i++) { 210 | leds[i] = CRGB::Black; 211 | FastLED.show(); // display this frame 212 | delay(1); 213 | } 214 | 215 | FastLED.show(); // display this frame 216 | 217 | while (true) { 218 | InputCommand command = readCommand(); 219 | if (command == InputCommand::Power || 220 | command == InputCommand::Brightness) 221 | return; 222 | 223 | // go idle for a while, converve power 224 | delay(250); 225 | } 226 | } 227 | 228 | int getBrightnessLevel() { 229 | int level = 0; 230 | for (int i = 0; i < brightnessCount; i++) { 231 | if (brightnessMap[i] >= brightness) { 232 | level = i; 233 | break; 234 | } 235 | } 236 | return level; 237 | } 238 | 239 | void adjustBrightness(int delta) { 240 | int level = getBrightnessLevel(); 241 | 242 | level += delta; 243 | if (level < 0) 244 | level = brightnessCount - 1; 245 | if (level >= brightnessCount) 246 | level = 0; 247 | 248 | brightness = brightnessMap[level]; 249 | FastLED.setBrightness(brightness); 250 | 251 | EEPROM.write(0, brightness); 252 | } 253 | 254 | uint8_t cycleBrightness() { 255 | adjustBrightness(1); 256 | 257 | if (brightness == brightnessMap[0]) 258 | return 8; 259 | 260 | return brightness; 261 | } 262 | 263 | // algorithm from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm 264 | void drawCircle(uint8_t x0, uint8_t y0, uint8_t radius, const CRGB color) 265 | { 266 | int a = radius, b = 0; 267 | int radiusError = 1 - a; 268 | 269 | if (radius == 0) { 270 | setPixelXY(x0, y0, color); 271 | return; 272 | } 273 | 274 | while (a >= b) 275 | { 276 | setPixelXY(a + x0, b + y0, color); 277 | setPixelXY(b + x0, a + y0, color); 278 | setPixelXY(-a + x0, b + y0, color); 279 | setPixelXY(-b + x0, a + y0, color); 280 | setPixelXY(-a + x0, -b + y0, color); 281 | setPixelXY(-b + x0, -a + y0, color); 282 | setPixelXY(a + x0, -b + y0, color); 283 | setPixelXY(b + x0, -a + y0, color); 284 | 285 | b++; 286 | if (radiusError < 0) 287 | radiusError += 2 * b + 1; 288 | else 289 | { 290 | a--; 291 | radiusError += 2 * (b - a + 1); 292 | } 293 | } 294 | } 295 | 296 | // scale the brightness of all pixels down 297 | void dimAll(byte value) 298 | { 299 | for (int i = 0; i < NUM_LEDS; i++) { 300 | leds[i].nscale8(value); 301 | } 302 | } 303 | 304 | // Patterns from FastLED example DemoReel100: https://github.com/FastLED/FastLED/blob/master/examples/DemoReel100/DemoReel100.ino 305 | 306 | uint8_t rainbow() 307 | { 308 | // FastLED's built-in rainbow generator 309 | fill_rainbow( leds, NUM_LEDS, gHue, 255 / NUM_LEDS); 310 | return 8; 311 | } 312 | 313 | void addGlitter( uint8_t chanceOfGlitter) 314 | { 315 | if ( random8() < chanceOfGlitter) { 316 | leds[ random16(NUM_LEDS) ] += CRGB::White; 317 | } 318 | } 319 | 320 | uint8_t rainbowWithGlitter() 321 | { 322 | // built-in FastLED rainbow, plus some random sparkly glitter 323 | rainbow(); 324 | addGlitter(80); 325 | return 8; 326 | } 327 | 328 | uint8_t rainbowSolid() 329 | { 330 | fill_solid(leds, NUM_LEDS, CHSV(gHue, 255, 255)); 331 | return 8; 332 | } 333 | 334 | uint8_t confetti() 335 | { 336 | // random colored speckles that blink in and fade smoothly 337 | fadeToBlackBy( leds, NUM_LEDS, 10); 338 | int pos = random16(NUM_LEDS); 339 | leds[pos] += CHSV( gHue + random8(64), 200, 255); 340 | return 8; 341 | } 342 | 343 | uint8_t sinelon1() 344 | { 345 | // a colored dot sweeping back and forth, with fading trails 346 | fadeToBlackBy( leds, NUM_LEDS, 20); 347 | int pos = beatsin16(13, 0, NUM_LEDS); 348 | leds[fibonacciToPhysicalOrder[pos]] += CHSV( gHue, 255, 192); 349 | return 8; 350 | } 351 | 352 | uint8_t sinelon2() 353 | { 354 | // a colored dot sweeping back and forth, with fading trails 355 | fadeToBlackBy( leds, NUM_LEDS, 20); 356 | int pos = beatsin16(13, 0, NUM_LEDS); 357 | leds[pos] += CHSV( gHue, 255, 192); 358 | return 8; 359 | } 360 | 361 | uint8_t bpm1() 362 | { 363 | // colored stripes pulsing at a defined Beats-Per-Minute (BPM) 364 | uint8_t BeatsPerMinute = 62; 365 | uint8_t beat = beatsin8( BeatsPerMinute, 64, 255); 366 | for ( int i = 0; i < NUM_LEDS; i++) { //9948 367 | leds[fibonacciToPhysicalOrder[i]] = ColorFromPalette(currentPalette, gHue + (i * 2), beat - gHue + (i * 10)); 368 | } 369 | 370 | return 8; 371 | } 372 | 373 | uint8_t bpm2() 374 | { 375 | // colored stripes pulsing at a defined Beats-Per-Minute (BPM) 376 | uint8_t BeatsPerMinute = 62; 377 | uint8_t beat = beatsin8( BeatsPerMinute, 64, 255); 378 | for ( int i = 0; i < NUM_LEDS; i++) { //9948 379 | leds[i] = ColorFromPalette(currentPalette, gHue + (i * 2), beat - gHue + (i * 10)); 380 | } 381 | 382 | return 8; 383 | } 384 | 385 | uint8_t juggle() { 386 | // eight colored dots, weaving in and out of sync with each other 387 | fadeToBlackBy( leds, NUM_LEDS, 20); 388 | byte dothue = 0; 389 | uint8_t dotcount = 3; 390 | for ( int i = 0; i < dotcount; i++) { 391 | leds[beatsin16(i + (dotcount - 1), 0, NUM_LEDS)] |= CHSV(dothue, 200, 255); 392 | dothue += (256 / dotcount); 393 | } 394 | 395 | return 8; 396 | } 397 | 398 | uint8_t juggle2() 399 | { 400 | static uint8_t numdots = 4; // Number of dots in use. 401 | static uint8_t faderate = 2; // How long should the trails be. Very low value = longer trails. 402 | static uint8_t hueinc = 255 / numdots - 1; // Incremental change in hue between each dot. 403 | static uint8_t thishue = 0; // Starting hue. 404 | static uint8_t curhue = 0; // The current hue 405 | static uint8_t thissat = 255; // Saturation of the colour. 406 | static uint8_t thisbright = 255; // How bright should the LED/display be. 407 | static uint8_t basebeat = 5; // Higher = faster movement. 408 | 409 | static uint8_t lastSecond = 99; // Static variable, means it's only defined once. This is our 'debounce' variable. 410 | uint8_t secondHand = (millis() / 1000) % 30; // IMPORTANT!!! Change '30' to a different value to change duration of the loop. 411 | 412 | if (lastSecond != secondHand) { // Debounce to make sure we're not repeating an assignment. 413 | lastSecond = secondHand; 414 | switch (secondHand) { 415 | case 0: numdots = 1; basebeat = 20; hueinc = 16; faderate = 2; thishue = 0; break; // You can change values here, one at a time , or altogether. 416 | case 10: numdots = 4; basebeat = 10; hueinc = 16; faderate = 8; thishue = 128; break; 417 | case 20: numdots = 8; basebeat = 3; hueinc = 0; faderate = 8; thishue = random8(); break; // Only gets called once, and not continuously for the next several seconds. Therefore, no rainbows. 418 | case 30: break; 419 | } 420 | } 421 | 422 | // Several colored dots, weaving in and out of sync with each other 423 | curhue = thishue; // Reset the hue values. 424 | fadeToBlackBy(leds, NUM_LEDS, faderate); 425 | for ( int i = 0; i < numdots; i++) { 426 | //beat16 is a FastLED 3.1 function 427 | leds[beatsin16(basebeat + i + numdots, 0, NUM_LEDS)] += CHSV(gHue + curhue, thissat, thisbright); 428 | curhue += hueinc; 429 | } 430 | 431 | return 8; 432 | } 433 | 434 | // based on FastLED example Fire2012WithPalette: https://github.com/FastLED/FastLED/blob/master/examples/Fire2012WithPalette/Fire2012WithPalette.ino 435 | void heatMap(CRGBPalette16 palette, bool up) 436 | { 437 | fill_solid(leds, NUM_LEDS, CRGB::Black); 438 | 439 | // Add entropy to random number generator; we use a lot of it. 440 | random16_add_entropy(random(256)); 441 | 442 | // COOLING: How much does the air cool as it rises? 443 | // Less cooling = taller flames. More cooling = shorter flames. 444 | // Default 55, suggested range 20-100 445 | uint8_t cooling = 55; 446 | 447 | // SPARKING: What chance (out of 255) is there that a new spark will be lit? 448 | // Higher chance = more roaring fire. Lower chance = more flickery fire. 449 | // Default 120, suggested range 50-200. 450 | uint8_t sparking = 120; 451 | 452 | // Array of temperature readings at each simulation cell 453 | static byte heat[kMatrixWidth + 3][kMatrixHeight + 3]; 454 | 455 | for (int x = 0; x < 10; x++) 456 | { 457 | // Step 1. Cool down every cell a little 458 | for (int y = 0; y < 10; y++) 459 | { 460 | heat[x][y] = qsub8(heat[x][y], random8(0, ((cooling * 10) / kMatrixHeight) + 2)); 461 | } 462 | 463 | // Step 2. Heat from each cell drifts 'up' and diffuses a little 464 | for (int y = 0; y < kMatrixHeight; y++) 465 | { 466 | heat[x][y] = (heat[x][y + 1] + heat[x][y + 2] + heat[x][y + 2]) / 3; 467 | } 468 | 469 | // Step 2. Randomly ignite new 'sparks' of heat 470 | if (random8() < sparking) 471 | { 472 | heat[x][maxY] = qadd8(heat[x][maxY], random8(160, 255)); 473 | } 474 | 475 | // Step 4. Map from heat cells to LED colors 476 | for (int y = 0; y < kMatrixHeight; y++) 477 | { 478 | uint8_t colorIndex = 0; 479 | 480 | if (up) 481 | colorIndex = heat[x][y]; 482 | else 483 | colorIndex = heat[x][(maxY) - y]; 484 | 485 | // Recommend that you use values 0-240 rather than 486 | // the usual 0-255, as the last 15 colors will be 487 | // 'wrapping around' from the hot end to the cold end, 488 | // which looks wrong. 489 | colorIndex = scale8(colorIndex, 240); 490 | 491 | // override color 0 to ensure a black background 492 | if (colorIndex != 0) 493 | { 494 | setPixelXY10(x, y, ColorFromPalette(palette, colorIndex, 255, LINEARBLEND)); 495 | } 496 | } 497 | } 498 | } 499 | 500 | uint8_t fire() 501 | { 502 | heatMap(HeatColors_p, true); 503 | 504 | return 30; 505 | } 506 | 507 | uint8_t water() 508 | { 509 | heatMap(IceColors_p, false); 510 | 511 | return 30; 512 | } 513 | 514 | uint8_t showSolidColor() 515 | { 516 | fill_solid(leds, NUM_LEDS, solidColor); 517 | 518 | return 30; 519 | } 520 | 521 | uint8_t incrementalDrift() { 522 | uint8_t stepwidth = 256 * (20 - 1) / NUM_LEDS; 523 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 524 | uint8_t bri = beatsin88(1 * 256 + (NUM_LEDS - i) * stepwidth, 0, 256); 525 | leds[fibonacciToPhysicalOrder[i]] = ColorFromPalette(gCurrentPalette, 2.5 * i + gHue, bri, LINEARBLEND); 526 | } 527 | 528 | return 8; 529 | } 530 | 531 | // Pride2015 by Mark Kriegsman: https://gist.github.com/kriegsman/964de772d64c502760e5 532 | // This function draws rainbows with an ever-changing, 533 | // widely-varying set of parameters. 534 | uint8_t pride(bool useFibonacciOrder) { 535 | static uint16_t sPseudotime = 0; 536 | static uint16_t sLastMillis = 0; 537 | static uint16_t sHue16 = 0; 538 | 539 | uint8_t sat8 = beatsin88( 87, 220, 250); 540 | uint8_t brightdepth = beatsin88( 341, 96, 224); 541 | uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256)); 542 | uint8_t msmultiplier = beatsin88(147, 23, 60); 543 | 544 | uint16_t hue16 = sHue16;//gHue * 256; 545 | uint16_t hueinc16 = beatsin88(113, 1, 3000); 546 | 547 | uint16_t ms = millis(); 548 | uint16_t deltams = ms - sLastMillis ; 549 | sLastMillis = ms; 550 | sPseudotime += deltams * msmultiplier; 551 | sHue16 += deltams * beatsin88( 400, 5, 9); 552 | uint16_t brightnesstheta16 = sPseudotime; 553 | 554 | for ( uint16_t i = 0 ; i < NUM_LEDS; i++) { 555 | hue16 += hueinc16; 556 | uint8_t hue8 = hue16 / 256; 557 | 558 | brightnesstheta16 += brightnessthetainc16; 559 | uint16_t b16 = sin16( brightnesstheta16 ) + 32768; 560 | 561 | uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536; 562 | uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536; 563 | bri8 += (255 - brightdepth); 564 | 565 | CRGB newcolor = CHSV( hue8, sat8, bri8); 566 | 567 | uint16_t pixelnumber = i; 568 | 569 | if (useFibonacciOrder) { 570 | pixelnumber = fibonacciToPhysicalOrder[(NUM_LEDS - 1) - pixelnumber]; 571 | } 572 | 573 | nblend(leds[pixelnumber], newcolor, 64); 574 | } 575 | 576 | return 15; 577 | } 578 | 579 | uint8_t pride1() 580 | { 581 | return pride(true); 582 | } 583 | 584 | uint8_t pride2() 585 | { 586 | return pride(false); 587 | } 588 | 589 | uint8_t radialPaletteShift() 590 | { 591 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 592 | // leds[i] = ColorFromPalette( currentPalette, gHue + sin8(i*16), brightness); 593 | uint8_t index = fibonacciToPhysicalOrder[(NUM_LEDS - 1) - i]; 594 | 595 | leds[index] = ColorFromPalette(gCurrentPalette, i + gHue, 255, LINEARBLEND); 596 | } 597 | 598 | return 8; 599 | } 600 | 601 | uint8_t horizontalPaletteBlend() 602 | { 603 | uint8_t offset = 0; 604 | 605 | for (uint8_t x = 0; x <= kMatrixWidth; x++) 606 | { 607 | CRGB color = ColorFromPalette(currentPalette, gHue + offset, 255, LINEARBLEND); 608 | 609 | for (uint8_t y = 0; y <= kMatrixHeight; y++) 610 | { 611 | setPixelXY(x, y, color); 612 | } 613 | 614 | offset++; 615 | } 616 | 617 | return 15; 618 | } 619 | 620 | uint8_t verticalPaletteBlend() 621 | { 622 | uint8_t offset = 0; 623 | 624 | for (uint8_t y = 0; y <= kMatrixHeight; y++) 625 | { 626 | CRGB color = ColorFromPalette(currentPalette, gHue + offset, 255, LINEARBLEND); 627 | 628 | for (uint8_t x = 0; x <= kMatrixWidth; x++) 629 | { 630 | setPixelXY(x, y, color); 631 | } 632 | 633 | offset++; 634 | } 635 | 636 | return 15; 637 | } 638 | 639 | uint8_t nyan() 640 | { 641 | static uint8_t offset = 0; 642 | 643 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 644 | uint8_t j = physicalToFibonacciOrder[i]; 645 | leds[i] = ColorFromPalette(gCurrentPalette, ledRadii[j] + offset, ledAngles[j] - offset); 646 | // leds[i] = CHSV(255 - ledRadii[j], 255, ledAngles[j] - offset); 647 | } 648 | 649 | EVERY_N_MILLISECONDS(15) { offset++; }; 650 | 651 | return 8; 652 | } 653 | 654 | uint8_t radialWavesWithCircular() 655 | { 656 | dimAll(253); 657 | 658 | static uint8_t prevB = 0; 659 | static bool spiral = false; 660 | 661 | uint8_t b = beatsin8(8); 662 | 663 | if(b < prevB){ 664 | random16_add_entropy(random()); 665 | if(random8() > 254) { 666 | spiral = true; 667 | } 668 | } 669 | 670 | prevB = b; 671 | 672 | // EVERY_N_SECONDS(5) { spiral = true; } 673 | 674 | if(spiral) { 675 | static uint8_t angle = random8(); 676 | static uint8_t radius = 255; 677 | 678 | setPixelAR(angle, radius, 24, 20, CRGB::White); 679 | 680 | if(radius < 1) { 681 | spiral = false; 682 | radius = 255; 683 | angle = random8(); 684 | } 685 | 686 | radius -= 1; 687 | angle -= 2; 688 | } 689 | 690 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 691 | uint8_t j = physicalToFibonacciOrder[i]; 692 | leds[i] |= ColorFromPalette(gCurrentPalette, ledRadii[j] - b); 693 | } 694 | 695 | return 1; 696 | } 697 | 698 | uint8_t circular() 699 | { 700 | dimAll(253); 701 | 702 | static uint8_t offset = 0; 703 | 704 | uint8_t angle = beat8(60); 705 | uint8_t radius = beatsin8(16); 706 | 707 | setPixelAR(angle, radius, 24, 20, ColorFromPalette(gCurrentPalette, offset)); 708 | // setPixelAR(angle, radius, 24, 20, CHSV(offset, 255, 255)); 709 | 710 | EVERY_N_MILLISECONDS(15) { offset++; }; 711 | 712 | return 8; 713 | } 714 | 715 | uint8_t radar() 716 | { 717 | dimAll(253); 718 | static uint8_t offset = 0; 719 | 720 | // uint8_t a = sin8(offset); 721 | // uint8_t r = cos8(offset); 722 | 723 | setPixelA(offset, 24, CRGB::Red); 724 | 725 | EVERY_N_MILLISECONDS(15) { offset++; }; 726 | 727 | return 1; 728 | } 729 | 730 | uint8_t angular() 731 | { 732 | static uint8_t offset = 0; 733 | 734 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 735 | uint8_t j = physicalToFibonacciOrder[i]; 736 | leds[i] = ColorFromPalette(gCurrentPalette, ledAngles[j] + offset); 737 | // leds[i] = CHSV(ledAngles[j] + offset, 255, 255); 738 | } 739 | 740 | EVERY_N_MILLISECONDS(15) { offset++; }; 741 | 742 | return 8; 743 | } 744 | 745 | uint8_t angular2() 746 | { 747 | static uint8_t offset = 0; 748 | 749 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 750 | uint8_t j = physicalToFibonacciOrder[i]; 751 | leds[i] = ColorFromPalette(gCurrentPalette, ledAngles[j] + offset, ledRadii[j]); 752 | // leds[i] = CHSV(ledAngles[j] + offset, 255, 255 - ledRadii[j]); 753 | } 754 | 755 | EVERY_N_MILLISECONDS(15) { offset++; }; 756 | 757 | return 8; 758 | } 759 | 760 | uint8_t radial() 761 | { 762 | static uint8_t offset = 0; 763 | 764 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 765 | uint8_t j = physicalToFibonacciOrder[i]; 766 | leds[i] = ColorFromPalette(gCurrentPalette, ledRadii[j] + offset); 767 | // leds[i] = CHSV(ledRadii[j] + offset, 255, 255); 768 | } 769 | 770 | EVERY_N_MILLISECONDS(15) { offset++; }; 771 | 772 | return 8; 773 | } 774 | 775 | uint8_t radial2() 776 | { 777 | static uint8_t offset = 0; 778 | 779 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 780 | uint8_t j = physicalToFibonacciOrder[i]; 781 | leds[i] = ColorFromPalette(gCurrentPalette, ledRadii[j] - offset); 782 | // leds[i] = CHSV(ledRadii[j] + offset, ledAngles[j], 255); 783 | } 784 | 785 | EVERY_N_MILLISECONDS(15) { offset++; }; 786 | 787 | return 8; 788 | } 789 | 790 | uint8_t radialWaves() 791 | { 792 | static uint8_t offset = 0; 793 | 794 | uint8_t b = beatsin8(8); 795 | 796 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 797 | uint8_t j = physicalToFibonacciOrder[i]; 798 | leds[i] = ColorFromPalette(gCurrentPalette, ledRadii[j] - b); 799 | // leds[i] = CHSV(ledRadii[j] + offset, ledAngles[j], 255); 800 | } 801 | 802 | EVERY_N_MILLISECONDS(15) { offset++; }; 803 | 804 | return 1; 805 | } 806 | 807 | uint8_t radial3() 808 | { 809 | static uint8_t offset = 0; 810 | 811 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 812 | uint8_t j = physicalToFibonacciOrder[i]; 813 | leds[i] = ColorFromPalette(gCurrentPalette, ledRadii[j] + offset, ledAngles[j] - offset); 814 | // leds[i] = CHSV(ledRadii[j] + offset, 255, ledAngles[j]); 815 | } 816 | 817 | EVERY_N_MILLISECONDS(15) { offset++; }; 818 | 819 | return 8; 820 | } 821 | 822 | CRGB scrollingHorizontalWashColor( uint8_t x, uint8_t y, unsigned long timeInMillis) 823 | { 824 | return CHSV( x + (timeInMillis / 10), 255, 255); 825 | } 826 | 827 | uint8_t horizontalRainbow() 828 | { 829 | unsigned long t = millis(); 830 | 831 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 832 | uint8_t j = physicalToFibonacciOrder[i]; 833 | leds[i] = scrollingHorizontalWashColor(coordsX[j], coordsY[j], t); 834 | } 835 | 836 | return 8; 837 | } 838 | 839 | CRGB scrollingVerticalWashColor( uint8_t x, uint8_t y, unsigned long timeInMillis) 840 | { 841 | return CHSV( y + (timeInMillis / 10), 255, 255); 842 | } 843 | 844 | uint8_t verticalRainbow() 845 | { 846 | unsigned long t = millis(); 847 | 848 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 849 | uint8_t j = physicalToFibonacciOrder[i]; 850 | leds[i] = scrollingVerticalWashColor(coordsX[j], coordsY[j], t); 851 | } 852 | 853 | return 8; 854 | } 855 | 856 | CRGB scrollingDiagonalWashColor( uint8_t x, uint8_t y, unsigned long timeInMillis) 857 | { 858 | return CHSV( x + y + (timeInMillis / 10), 255, 255); 859 | } 860 | 861 | uint8_t diagonalRainbow() 862 | { 863 | unsigned long t = millis(); 864 | 865 | for (uint8_t i = 0; i < NUM_LEDS; i++) { 866 | uint8_t j = physicalToFibonacciOrder[i]; 867 | leds[i] = scrollingDiagonalWashColor(coordsX[j], coordsY[j], t); 868 | } 869 | 870 | return 8; 871 | } 872 | 873 | uint8_t wave() 874 | { 875 | const uint8_t scale = 256 / kMatrixWidth; 876 | 877 | static uint8_t rotation = 0; 878 | static uint8_t theta = 0; 879 | static uint8_t waveCount = 1; 880 | 881 | uint8_t n = 0; 882 | 883 | switch (rotation) { 884 | case 0: 885 | for (int x = 0; x < kMatrixWidth; x++) { 886 | n = quadwave8(x * 2 + theta) / scale; 887 | setPixelXY(x, n, ColorFromPalette(currentPalette, x + gHue, 255, LINEARBLEND)); 888 | if (waveCount == 2) 889 | setPixelXY(x, maxY - n, ColorFromPalette(currentPalette, x + gHue, 255, LINEARBLEND)); 890 | } 891 | break; 892 | 893 | case 1: 894 | for (int y = 0; y < kMatrixHeight; y++) { 895 | n = quadwave8(y * 2 + theta) / scale; 896 | setPixelXY(n, y, ColorFromPalette(currentPalette, y + gHue, 255, LINEARBLEND)); 897 | if (waveCount == 2) 898 | setPixelXY(maxX - n, y, ColorFromPalette(currentPalette, y + gHue, 255, LINEARBLEND)); 899 | } 900 | break; 901 | 902 | case 2: 903 | for (int x = 0; x < kMatrixWidth; x++) { 904 | n = quadwave8(x * 2 - theta) / scale; 905 | setPixelXY(x, n, ColorFromPalette(currentPalette, x + gHue)); 906 | if (waveCount == 2) 907 | setPixelXY(x, maxY - n, ColorFromPalette(currentPalette, x + gHue, 255, LINEARBLEND)); 908 | } 909 | break; 910 | 911 | case 3: 912 | for (int y = 0; y < kMatrixHeight; y++) { 913 | n = quadwave8(y * 2 - theta) / scale; 914 | setPixelXY(n, y, ColorFromPalette(currentPalette, y + gHue, 255, LINEARBLEND)); 915 | if (waveCount == 2) 916 | setPixelXY(maxX - n, y, ColorFromPalette(currentPalette, y + gHue, 255, LINEARBLEND)); 917 | } 918 | break; 919 | } 920 | 921 | dimAll(255); 922 | 923 | EVERY_N_SECONDS(10) 924 | { 925 | rotation = random(0, 4); 926 | // waveCount = random(1, 3); 927 | }; 928 | 929 | EVERY_N_MILLISECONDS(7) { 930 | theta++; 931 | } 932 | 933 | return 8; 934 | } 935 | 936 | uint8_t pulse() 937 | { 938 | dimAll(200); 939 | 940 | uint8_t maxSteps = 16; 941 | static uint8_t step = maxSteps; 942 | static uint8_t centerX = 0; 943 | static uint8_t centerY = 0; 944 | float fadeRate = 0.8; 945 | 946 | if (step >= maxSteps) 947 | { 948 | centerX = random(kMatrixWidth); 949 | centerY = random(kMatrixWidth); 950 | step = 0; 951 | } 952 | 953 | if (step == 0) 954 | { 955 | drawCircle(centerX, centerY, step, ColorFromPalette(currentPalette, gHue, 255, LINEARBLEND)); 956 | step++; 957 | } 958 | else 959 | { 960 | if (step < maxSteps) 961 | { 962 | // initial pulse 963 | drawCircle(centerX, centerY, step, ColorFromPalette(currentPalette, gHue, pow(fadeRate, step - 2) * 255, LINEARBLEND)); 964 | 965 | // secondary pulse 966 | if (step > 3) { 967 | drawCircle(centerX, centerY, step - 3, ColorFromPalette(currentPalette, gHue, pow(fadeRate, step - 2) * 255, LINEARBLEND)); 968 | } 969 | 970 | step++; 971 | } 972 | else 973 | { 974 | step = -1; 975 | } 976 | } 977 | 978 | return 30; 979 | } 980 | 981 | // ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb 982 | // This function draws color waves with an ever-changing, 983 | // widely-varying set of parameters, using a color palette. 984 | void colorwaves( CRGB* ledarray, uint16_t numleds, CRGBPalette16& palette, bool useFibonacciOrder) 985 | { 986 | static uint16_t sPseudotime = 0; 987 | static uint16_t sLastMillis = 0; 988 | static uint16_t sHue16 = 0; 989 | 990 | // uint8_t sat8 = beatsin88( 87, 220, 250); 991 | uint8_t brightdepth = beatsin88( 341, 96, 224); 992 | uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256)); 993 | uint8_t msmultiplier = beatsin88(147, 23, 60); 994 | 995 | uint16_t hue16 = sHue16;//gHue * 256; 996 | uint16_t hueinc16 = beatsin88(113, 300, 1500); 997 | 998 | uint16_t ms = millis(); 999 | uint16_t deltams = ms - sLastMillis ; 1000 | sLastMillis = ms; 1001 | sPseudotime += deltams * msmultiplier; 1002 | sHue16 += deltams * beatsin88( 400, 5, 9); 1003 | uint16_t brightnesstheta16 = sPseudotime; 1004 | 1005 | for ( uint16_t i = 0 ; i < numleds; i++) { 1006 | hue16 += hueinc16; 1007 | uint8_t hue8 = hue16 / 256; 1008 | uint16_t h16_128 = hue16 >> 7; 1009 | if ( h16_128 & 0x100) { 1010 | hue8 = 255 - (h16_128 >> 1); 1011 | } else { 1012 | hue8 = h16_128 >> 1; 1013 | } 1014 | 1015 | brightnesstheta16 += brightnessthetainc16; 1016 | uint16_t b16 = sin16( brightnesstheta16 ) + 32768; 1017 | 1018 | uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536; 1019 | uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536; 1020 | bri8 += (255 - brightdepth); 1021 | 1022 | uint8_t index = hue8; 1023 | //index = triwave8( index); 1024 | index = scale8( index, 240); 1025 | 1026 | CRGB newcolor = ColorFromPalette( palette, index, bri8); 1027 | 1028 | uint16_t pixelnumber = i; 1029 | 1030 | if (useFibonacciOrder) { 1031 | pixelnumber = fibonacciToPhysicalOrder[(numleds - 1) - pixelnumber]; 1032 | } 1033 | 1034 | nblend( ledarray[pixelnumber], newcolor, 128); 1035 | } 1036 | } 1037 | 1038 | uint8_t colorWaves1() 1039 | { 1040 | colorwaves( leds, NUM_LEDS, gCurrentPalette, true); 1041 | return 20; 1042 | } 1043 | 1044 | uint8_t colorWaves2() 1045 | { 1046 | colorwaves( leds, NUM_LEDS, gCurrentPalette, false); 1047 | return 20; 1048 | } 1049 | 1050 | // Alternate rendering function just scrolls the current palette 1051 | // across the defined LED strip. 1052 | void palettetest( CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurrentPalette) 1053 | { 1054 | static uint8_t startindex = 0; 1055 | startindex--; 1056 | fill_palette( ledarray, numleds, startindex, (256 / NUM_LEDS) + 1, gCurrentPalette, 255, LINEARBLEND); 1057 | } 1058 | 1059 | typedef uint8_t (*SimplePattern)(); 1060 | typedef SimplePattern SimplePatternList[]; 1061 | 1062 | // List of patterns to cycle through. Each is defined as a separate function below. 1063 | 1064 | #include "Life.h" 1065 | #include "Twinkles.h" 1066 | #include "Noise.h" 1067 | 1068 | const SimplePatternList patterns = { 1069 | // Fibonacci patterns 1070 | pride1, 1071 | pride2, 1072 | colorWaves1, 1073 | colorWaves2, 1074 | incrementalDrift, 1075 | 1076 | // palette shifting/blending patterns 1077 | radialPaletteShift, 1078 | verticalPaletteBlend, 1079 | horizontalPaletteBlend, 1080 | horizontalRainbow, 1081 | verticalRainbow, 1082 | diagonalRainbow, 1083 | 1084 | // noise patterns 1085 | fireNoise, 1086 | fireNoise2, 1087 | lavaNoise, 1088 | rainbowNoise, 1089 | rainbowStripeNoise, 1090 | partyNoise, 1091 | forestNoise, 1092 | cloudNoise, 1093 | oceanNoise, 1094 | blackAndWhiteNoise, 1095 | blackAndBlueNoise, 1096 | 1097 | // radial patterns 1098 | radialWavesWithCircular, 1099 | radialWaves, 1100 | radial, 1101 | radial2, 1102 | radial3, 1103 | nyan, 1104 | circular, 1105 | angular, 1106 | angular2, 1107 | 1108 | // 2D XY patterns 1109 | wave, 1110 | life, 1111 | pulse, 1112 | fire, 1113 | water, 1114 | 1115 | // 1D patterns 1116 | rainbow, 1117 | rainbowWithGlitter, 1118 | rainbowSolid, 1119 | sinelon1, 1120 | sinelon2, 1121 | bpm1, 1122 | bpm2, 1123 | juggle, 1124 | juggle2, 1125 | confetti, 1126 | rainbowTwinkles, 1127 | snowTwinkles, 1128 | cloudTwinkles, 1129 | incandescentTwinkles, 1130 | 1131 | showSolidColor, 1132 | }; 1133 | 1134 | int patternCount = ARRAY_SIZE(patterns); 1135 | 1136 | void moveTo(int index) { 1137 | patternIndex = index; 1138 | 1139 | if (patternIndex >= patternCount) 1140 | patternIndex = 0; 1141 | else if (patternIndex < 0) 1142 | patternIndex = patternCount - 1; 1143 | 1144 | fill_solid(leds, NUM_LEDS, CRGB::Black); 1145 | 1146 | EEPROM.write(1, patternIndex); 1147 | } 1148 | 1149 | void move(int delta) { 1150 | moveTo(patternIndex + delta); 1151 | } 1152 | 1153 | void loadSettings() { 1154 | // load settings from EEPROM 1155 | 1156 | // brightness 1157 | brightness = EEPROM.read(0); 1158 | if (brightness < 1) 1159 | brightness = 1; 1160 | else if (brightness > 255) 1161 | brightness = 255; 1162 | 1163 | // patternIndex 1164 | patternIndex = EEPROM.read(1); 1165 | if (patternIndex < 0) 1166 | patternIndex = 0; 1167 | else if (patternIndex >= patternCount) 1168 | patternIndex = patternCount - 1; 1169 | 1170 | // solidColor 1171 | solidColor.r = EEPROM.read(2); 1172 | solidColor.g = EEPROM.read(3); 1173 | solidColor.b = EEPROM.read(4); 1174 | 1175 | if (solidColor.r == 0 && solidColor.g == 0 && solidColor.b == 0) 1176 | solidColor = CRGB::White; 1177 | } 1178 | 1179 | void setSolidColor(CRGB color) { 1180 | solidColor = color; 1181 | 1182 | EEPROM.write(2, solidColor.r); 1183 | EEPROM.write(3, solidColor.g); 1184 | EEPROM.write(4, solidColor.b); 1185 | 1186 | moveTo(patternCount - 1); 1187 | } 1188 | 1189 | void handleInput(unsigned int requestedDelay) { 1190 | unsigned int requestedDelayTimeout = millis() + requestedDelay; 1191 | 1192 | while (true) { 1193 | command = readCommand(defaultHoldDelay); 1194 | 1195 | if (command != InputCommand::None) { 1196 | Serial.print("command: "); 1197 | Serial.println((int) command); 1198 | } 1199 | 1200 | if (command == InputCommand::Up) { 1201 | move(1); 1202 | break; 1203 | } 1204 | else if (command == InputCommand::Down) { 1205 | move(-1); 1206 | break; 1207 | } 1208 | else if (command == InputCommand::Brightness) { 1209 | if (isHolding || cycleBrightness() == 0) { 1210 | heldButtonHasBeenHandled(); 1211 | powerOff(); 1212 | break; 1213 | } 1214 | } 1215 | else if (command == InputCommand::Power) { 1216 | powerOff(); 1217 | break; 1218 | } 1219 | else if (command == InputCommand::BrightnessUp) { 1220 | adjustBrightness(1); 1221 | } 1222 | else if (command == InputCommand::BrightnessDown) { 1223 | adjustBrightness(-1); 1224 | } 1225 | else if (command == InputCommand::PlayMode) { // toggle pause/play 1226 | autoplayEnabled = !autoplayEnabled; 1227 | } 1228 | //else if (command == InputCommand::Palette) { // cycle color pallete 1229 | // effects.CyclePalette(); 1230 | //} 1231 | 1232 | // pattern buttons 1233 | 1234 | else if (command == InputCommand::Pattern1) { 1235 | moveTo(0); 1236 | break; 1237 | } 1238 | else if (command == InputCommand::Pattern2) { 1239 | moveTo(1); 1240 | break; 1241 | } 1242 | else if (command == InputCommand::Pattern3) { 1243 | moveTo(2); 1244 | break; 1245 | } 1246 | else if (command == InputCommand::Pattern4) { 1247 | moveTo(3); 1248 | break; 1249 | } 1250 | else if (command == InputCommand::Pattern5) { 1251 | moveTo(4); 1252 | break; 1253 | } 1254 | else if (command == InputCommand::Pattern6) { 1255 | moveTo(5); 1256 | break; 1257 | } 1258 | else if (command == InputCommand::Pattern7) { 1259 | moveTo(6); 1260 | break; 1261 | } 1262 | else if (command == InputCommand::Pattern8) { 1263 | moveTo(7); 1264 | break; 1265 | } 1266 | else if (command == InputCommand::Pattern9) { 1267 | moveTo(8); 1268 | break; 1269 | } 1270 | else if (command == InputCommand::Pattern10) { 1271 | moveTo(9); 1272 | break; 1273 | } 1274 | else if (command == InputCommand::Pattern11) { 1275 | moveTo(10); 1276 | break; 1277 | } 1278 | else if (command == InputCommand::Pattern12) { 1279 | moveTo(11); 1280 | break; 1281 | } 1282 | 1283 | // custom color adjustment buttons 1284 | 1285 | else if (command == InputCommand::RedUp) { 1286 | solidColor.red += 1; 1287 | setSolidColor(solidColor); 1288 | break; 1289 | } 1290 | else if (command == InputCommand::RedDown) { 1291 | solidColor.red -= 1; 1292 | setSolidColor(solidColor); 1293 | break; 1294 | } 1295 | else if (command == InputCommand::GreenUp) { 1296 | solidColor.green += 1; 1297 | setSolidColor(solidColor); 1298 | 1299 | break; 1300 | } 1301 | else if (command == InputCommand::GreenDown) { 1302 | solidColor.green -= 1; 1303 | setSolidColor(solidColor); 1304 | break; 1305 | } 1306 | else if (command == InputCommand::BlueUp) { 1307 | solidColor.blue += 1; 1308 | setSolidColor(solidColor); 1309 | break; 1310 | } 1311 | else if (command == InputCommand::BlueDown) { 1312 | solidColor.blue -= 1; 1313 | setSolidColor(solidColor); 1314 | break; 1315 | } 1316 | 1317 | // color buttons 1318 | 1319 | else if (command == InputCommand::Red) { 1320 | setSolidColor(CRGB::Red); 1321 | break; 1322 | } 1323 | else if (command == InputCommand::RedOrange) { 1324 | setSolidColor(CRGB::OrangeRed); 1325 | break; 1326 | } 1327 | else if (command == InputCommand::Orange) { 1328 | setSolidColor(CRGB::Orange); 1329 | break; 1330 | } 1331 | else if (command == InputCommand::YellowOrange) { 1332 | setSolidColor(CRGB::Goldenrod); 1333 | break; 1334 | } 1335 | else if (command == InputCommand::Yellow) { 1336 | setSolidColor(CRGB::Yellow); 1337 | break; 1338 | } 1339 | 1340 | else if (command == InputCommand::Green) { // Red, Green, and Blue buttons can be used by ColorInvaders game, which is the next to last pattern 1341 | setSolidColor(CRGB::Green); 1342 | break; 1343 | } 1344 | else if (command == InputCommand::Lime) { 1345 | setSolidColor(CRGB::Lime); 1346 | break; 1347 | } 1348 | else if (command == InputCommand::Aqua) { 1349 | setSolidColor(CRGB::Aqua); 1350 | break; 1351 | } 1352 | else if (command == InputCommand::Teal) { 1353 | setSolidColor(CRGB::Teal); 1354 | break; 1355 | } 1356 | else if (command == InputCommand::Navy) { 1357 | setSolidColor(CRGB::Navy); 1358 | break; 1359 | } 1360 | 1361 | else if (command == InputCommand::Blue) { // Red, Green, and Blue buttons can be used by ColorInvaders game, which is the next to last pattern 1362 | setSolidColor(CRGB::Blue); 1363 | break; 1364 | } 1365 | else if (command == InputCommand::RoyalBlue) { 1366 | setSolidColor(CRGB::RoyalBlue); 1367 | break; 1368 | } 1369 | else if (command == InputCommand::Purple) { 1370 | setSolidColor(CRGB::Purple); 1371 | break; 1372 | } 1373 | else if (command == InputCommand::Indigo) { 1374 | setSolidColor(CRGB::Indigo); 1375 | break; 1376 | } 1377 | else if (command == InputCommand::Magenta) { 1378 | setSolidColor(CRGB::Magenta); 1379 | break; 1380 | } 1381 | 1382 | else if (command == InputCommand::White) { 1383 | setSolidColor(CRGB::White); 1384 | break; 1385 | } 1386 | else if (command == InputCommand::Pink) { 1387 | setSolidColor(CRGB::Pink); 1388 | break; 1389 | } 1390 | else if (command == InputCommand::LightPink) { 1391 | setSolidColor(CRGB::LightPink); 1392 | break; 1393 | } 1394 | else if (command == InputCommand::BabyBlue) { 1395 | setSolidColor(CRGB::CornflowerBlue); 1396 | break; 1397 | } 1398 | else if (command == InputCommand::LightBlue) { 1399 | setSolidColor(CRGB::LightBlue); 1400 | break; 1401 | } 1402 | 1403 | if (millis() >= requestedDelayTimeout) 1404 | break; 1405 | } 1406 | } 1407 | 1408 | void setup() 1409 | { 1410 | FastLED.addLeds(leds, NUM_LEDS); 1411 | FastLED.setCorrection(Typical8mmPixel); 1412 | FastLED.setBrightness(brightness); 1413 | FastLED.setDither(false); 1414 | fill_solid(leds, NUM_LEDS, solidColor); 1415 | FastLED.show(); 1416 | 1417 | // Serial.begin(9600); 1418 | 1419 | // Initialize the IR receiver 1420 | irReceiver.enableIRIn(); 1421 | irReceiver.blink13(true); 1422 | 1423 | loadSettings(); 1424 | 1425 | FastLED.setBrightness(brightness); 1426 | FastLED.setDither(brightness < 255); 1427 | 1428 | noisex = random16(); 1429 | noisey = random16(); 1430 | noisez = random16(); 1431 | } 1432 | 1433 | void loop() 1434 | { 1435 | // Add entropy to random number generator; we use a lot of it. 1436 | random16_add_entropy(random()); 1437 | 1438 | uint8_t requestedDelay = patterns[patternIndex](); 1439 | 1440 | // send the 'leds' array out to the actual LED strip 1441 | FastLED.show(); 1442 | 1443 | handleInput(requestedDelay); 1444 | 1445 | if (autoplayEnabled && millis() > autoPlayTimout) { 1446 | move(1); 1447 | autoPlayTimout = millis() + (autoPlayDurationSeconds * 1000); 1448 | } 1449 | 1450 | // blend the current palette to the next 1451 | EVERY_N_MILLISECONDS(40) { 1452 | nblendPaletteTowardPalette(currentPalette, targetPalette, 16); 1453 | } 1454 | 1455 | EVERY_N_MILLISECONDS( 40 ) { 1456 | gHue++; // slowly cycle the "base color" through the rainbow 1457 | } 1458 | 1459 | // slowly change to a new palette 1460 | EVERY_N_SECONDS(SECONDS_PER_PALETTE) { 1461 | paletteIndex++; 1462 | if (paletteIndex >= paletteCount) paletteIndex = 0; 1463 | targetPalette = palettes[paletteIndex]; 1464 | }; 1465 | 1466 | // slowly change to a new cpt-city gradient palette 1467 | EVERY_N_SECONDS( SECONDS_PER_PALETTE ) { 1468 | gCurrentPaletteNumber = addmod8( gCurrentPaletteNumber, 1, gGradientPaletteCount); 1469 | gTargetPalette = gGradientPalettes[ gCurrentPaletteNumber ]; 1470 | } 1471 | 1472 | // blend the current cpt-city gradient palette to the next 1473 | EVERY_N_MILLISECONDS(40) { 1474 | nblendPaletteTowardPalette( gCurrentPalette, gTargetPalette, 16); 1475 | } 1476 | } 1477 | 1478 | --------------------------------------------------------------------------------