├── .gitignore ├── Animations.ino ├── DevelopmentTools.ino ├── FunkyNoise_SmartMatrix_Edition.ino ├── HelperFunctions.ino ├── LICENSE ├── Menu.ino ├── Palettes.ino ├── README.md └── experimental.ino /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | -------------------------------------------------------------------------------- /Animations.ino: -------------------------------------------------------------------------------- 1 | /* 2 | A bunch of animations demonstrating how to creatively combine 3 | simple functions for nice effects. 4 | 5 | MirroredNoise a symmetric noise pattern 6 | RedClouds upstreaming clouds 7 | Lavalamp1 - Lavlamp 5 8 | Constrained1 9 | RelativeMotion1 10 | Water 11 | Bubbles1 12 | ShowPalette 13 | 14 | (list is uncomplete) 15 | ----------------------------------------------------------------- 16 | */ 17 | 18 | 19 | // MirroredNoise() draws a symmetric noise pattern 20 | // 108 fps 21 | 22 | void MirroredNoise() { 23 | 24 | // move within the noise space 25 | x[0] += 100; 26 | z[0] += 100; 27 | scale_x[0] = 4000; 28 | scale_y[0] = 4000; 29 | 30 | // calculate the noise array 31 | FillNoise(0); 32 | 33 | currentPalette = RainbowStripeColors_p; 34 | noisesmoothing = 10; 35 | 36 | for(int i = 0; i < kMatrixWidth; i++) { 37 | for(int j = 0; j < kMatrixHeight; j++) { 38 | 39 | // map the noise values down 40 | uint16_t index = ( noise[0][i][j] + noise[0][kMatrixWidth - 1 - i][j] ) / 2; 41 | uint16_t bri = 255; 42 | // assign a color from the HSV space 43 | CRGB color = ColorFromPalette( currentPalette, index, bri); 44 | 45 | leds[XY(i,j)] = color; 46 | } 47 | } 48 | } 49 | 50 | 51 | // RedClouds() draws a constrained noise space with a palette 52 | // softening the edges. 53 | // Upstreaming red clouds. 54 | // 108 fps 55 | 56 | void RedClouds() { 57 | 58 | // clear the screenbuffer 59 | CLS(); 60 | 61 | PaletteRed(); 62 | colorshift = 240; 63 | 64 | // move within the noise space 65 | x[0] = beatsin16(1)*10; 66 | y[0] += 2000; 67 | z[0] += 100; 68 | scale_x[0] = 6000; 69 | scale_x[0] = 6000; 70 | 71 | // calculate the noise array 72 | FillNoise(0); 73 | 74 | for(int i = 0; i < kMatrixWidth; i++) { 75 | for(int j = 0; j < kMatrixHeight; j++) { 76 | 77 | // map the noise values down to a byte range 78 | uint16_t index = noise[0][i][j]; 79 | uint16_t bri = 255; 80 | // assign a color depending on the actual palette 81 | CRGB color = ColorFromPalette( currentPalette, index + colorshift, bri); 82 | 83 | // draw only the part lower than the threshold 84 | if (index < 128) { 85 | leds[XY(i,j)] = color; 86 | } 87 | } 88 | } 89 | } 90 | 91 | 92 | // Lavalamp1 93 | // works good with the RedBlack palette 94 | 95 | void Lavalamp1() { 96 | 97 | PaletteRed(); 98 | colorshift = 0; 99 | 100 | x[0] = beatsin16(3, 200, 64000); 101 | y[0] += 100; 102 | z[0] = 7000; 103 | scale_x[0] = 6000; 104 | scale_y[0] = 8000; 105 | FillNoise(0); 106 | 107 | x[1] = beatsin16(2, 200, 64000); 108 | y[1] += 130; 109 | z[1] = 7000; 110 | scale_x[1] = 6000; 111 | scale_y[1] = 8000; 112 | FillNoise(1); 113 | 114 | x[2] = beatsin16(4, 200, 6400); 115 | y[2] += 1000; 116 | z[2] = 3000; 117 | scale_x[2] = 7000; 118 | scale_y[2] = 8000; 119 | FillNoise(2); 120 | 121 | noisesmoothing = 200; 122 | 123 | MergeMethod1(2); 124 | //Show3Layers(); 125 | } 126 | 127 | 128 | // with a scrolling palette 129 | 130 | void Lavalamp2() { 131 | 132 | currentPalette = PartyColors_p; 133 | 134 | noisesmoothing = 200; 135 | 136 | x[0] = beatsin16(3, 200, 64000); 137 | y[0] = beatsin16(4, 200, 64000); 138 | z[0] = 7000; 139 | scale_x[0] = beatsin16(2, 6000, 8000); 140 | scale_y[0] = beatsin16(1, 4000, 12000); 141 | FillNoise(0); 142 | 143 | x[1] = beatsin16(5, 200, 64000); 144 | y[1] = beatsin16(6, 200, 64000); 145 | z[1] = 6000; 146 | scale_x[1] = 6000; 147 | scale_y[1] = 8000; 148 | FillNoise(1); 149 | 150 | x[2] = beatsin16(4, 200, 6400); 151 | y[2] += 1000; 152 | z[2] = 3000; 153 | scale_x[2] = 7000; 154 | scale_y[2] = 8000; 155 | FillNoise(2); 156 | 157 | colorshift++; 158 | 159 | MergeMethod1(2); 160 | //Show3Layers(); 161 | } 162 | 163 | 164 | // a very slow one 165 | 166 | void Lavalamp3() { 167 | 168 | noisesmoothing = 40; 169 | currentPalette = ForestColors_p; 170 | 171 | y[0] += 100; 172 | z[0] = 7000; 173 | scale_x[0] = 6000; 174 | scale_y[0] = 6000; 175 | FillNoise(0); 176 | 177 | y[1] += 200; 178 | z[1] = 3000; 179 | scale_x[1] = 7000; 180 | scale_y[1] = 8000; 181 | FillNoise(1); 182 | 183 | y[2] += 250; 184 | z[2] = 6000; 185 | scale_x[2] = 20000; 186 | scale_y[2] = 8000; 187 | FillNoise(2); 188 | 189 | MergeMethod1(1); 190 | //Show3Layers(); 191 | } 192 | 193 | 194 | // the palette can also be defined within the animation 195 | 196 | void Lavalamp4() { 197 | 198 | currentPalette = CRGBPalette16( 199 | CHSV( 0, 255, 0 ), 200 | CHSV( 0, 255, 255 ), 201 | CHSV( 0, 255, 0 ), 202 | CHSV( 160, 255, 255 )); 203 | 204 | noisesmoothing = 150; 205 | 206 | y[0] += 100; 207 | z[0] = 7000; 208 | scale_x[0] = 6000; 209 | scale_y[0] = 6000; 210 | FillNoise(0); 211 | 212 | y[1] += 200; 213 | z[1] = 3000; 214 | scale_x[1] = 7000; 215 | scale_y[1] = 8000; 216 | FillNoise(1); 217 | 218 | y[2] += 250; 219 | z[2] = 6000; 220 | scale_x[2] = 20000; 221 | scale_y[2] = 8000; 222 | FillNoise(2); 223 | 224 | MergeMethod1(2); 225 | //Show3Layers(); 226 | } 227 | 228 | 229 | // lets play with the scaling of 2 layers 230 | 231 | void Lavalamp5() { 232 | 233 | currentPalette = CRGBPalette16( 234 | CHSV( 0, 255, 0 ), 235 | CHSV( 0, 200, 255 ), 236 | CHSV( 63, 150, 255 ), 237 | CHSV( 160, 255, 0 )); 238 | 239 | noisesmoothing = 50; 240 | 241 | y[0] += 1000; 242 | z[0] = 7000; 243 | scale_x[0] = beatsin16(3, 1000, 20000); 244 | scale_y[0] = 6000; 245 | FillNoise(0); 246 | 247 | y[1] += 2000; 248 | z[1] = 3000; 249 | scale_x[1] = beatsin16(4, 1000, 20000); 250 | scale_y[1] = 8000; 251 | FillNoise(1); 252 | 253 | y[2] += 3000; 254 | z[2] = 6000; 255 | scale_x[2] = beatsin16(5, 1000, 20000); 256 | scale_y[2] = 8000; 257 | FillNoise(2); 258 | 259 | MergeMethod2(3); 260 | //Show3Layers(); 261 | } 262 | 263 | 264 | // 2 layers of constrained noise using differnt palettes for color mapping 265 | 266 | void Constrained1() { 267 | 268 | noisesmoothing = 100; 269 | colorshift = 0; 270 | 271 | x[0] += 2000; 272 | scale_x[0] = 6000; 273 | scale_y[0] = 6000; 274 | FillNoise(0); 275 | 276 | x[1] -= 2000; 277 | scale_x[1] = 6000; 278 | scale_y[1] = 6000; 279 | FillNoise(1); 280 | 281 | CLS(); 282 | 283 | // define a palette used for layer 0 284 | currentPalette = CRGBPalette16( 285 | CHSV( 0, 255, 0 ), 286 | CHSV( 0, 255, 0 ), 287 | CHSV( 0, 255, 255 ), 288 | CHSV( 160, 255, 0 )); 289 | 290 | // map layer 0 (red) for noise values between 100 and 200 291 | ConstrainedMapping( 0, 100, 200, 1); 292 | 293 | // palette for the second layer 294 | currentPalette = CRGBPalette16( 295 | CHSV( 0, 255, 0 ), 296 | CHSV( 0, 255, 0 ), 297 | CHSV( 160, 255, 255 ), 298 | CHSV( 160, 255, 0 )); 299 | 300 | // map layer 1 (blue) for noise values between 100 and 200 301 | ConstrainedMapping( 1, 100, 200, 1); 302 | } 303 | 304 | 305 | // move 2 layers relative to each other 306 | 307 | void RelativeMotion1() { 308 | 309 | currentPalette = CRGBPalette16( 310 | CHSV( 0, 255, 0 ), 311 | CHSV( 80, 255, 255 ), 312 | CHSV( 60, 255, 255 ), 313 | CHSV( 0, 255, 0 )); 314 | 315 | colorshift = beatsin8(10); 316 | noisesmoothing = 100; 317 | 318 | x[0] = 5 * beatsin16(2, 15000, 40000); 319 | y[0] = 5 * beatsin16(3, 15000, 40000); 320 | z[0] += 100; 321 | scale_x[0] = 6000 + beatsin16(30, 0, 4000); 322 | scale_y[0] = 8000 + beatsin16(27, 0, 4000); 323 | FillNoise(0); 324 | 325 | x[1] = x[0] + (5 * beatsin16(30, 0, 10000)) - 25000; 326 | y[1] = y[0] + (5 * beatsin16(40, 0, 10000)) - 25000; 327 | z[1] += 100; 328 | scale_x[1] = 6000 + beatsin16(30, 0, 3000); 329 | scale_y[1] = 8000 + beatsin16(27, 0, 3000); 330 | FillNoise(1); 331 | 332 | MergeMethod3(1); 333 | } 334 | 335 | 336 | // first approach of a water simulation 337 | // uses a beatsin function with phase shift 338 | 339 | void Water() { 340 | 341 | currentPalette = OceanColors_p; 342 | colorshift++; 343 | noisesmoothing = 200; 344 | 345 | // 2 sinewaves shiftet by 63 (90 degrees) 346 | // results in a circular motion 347 | x[0] = 10 * beatsin(10, 0, 10000, 0); 348 | y[0] = 10 * beatsin(10, 0, 10000, 63); 349 | z[0] += 1000; 350 | scale_x[0] = 6000; 351 | scale_y[0] = 8000; 352 | FillNoise(0); 353 | 354 | x[1] = x[0] + (10 * beatsin(60, 0, 10000, 0)) - 50000; 355 | y[1] = y[0] + (10 * beatsin(60, 0, 10000, 63)) - 50000; 356 | z[1] += 1000; 357 | scale_x[1] = 6000 ; 358 | scale_y[1] = 8000; 359 | FillNoise(1); 360 | 361 | MergeMethod3(3); 362 | } 363 | 364 | 365 | // outlined bubbles by constrained mapping + palette 366 | 367 | void Bubbles1() { 368 | 369 | noisesmoothing = 200; 370 | PaletteRed(); 371 | colorshift = 0; 372 | 373 | x[0] = beatsin16(7); 374 | y[0] += 2000; 375 | z[0] = 7000; 376 | scale_x[0] = 6000; 377 | scale_y[0] = 6000; 378 | FillNoise(0); 379 | 380 | x[1] = beatsin16(8); 381 | y[1] += 3000; 382 | z[1] = 10000; 383 | scale_x[1] = 6000; 384 | scale_y[1] = 6000; 385 | FillNoise(1); 386 | 387 | CLS(); 388 | 389 | ConstrainedMapping(1, 0, 100, 3); 390 | ConstrainedMapping(0, 0, 100, 3); 391 | } 392 | 393 | 394 | // layer2 movving arround a layer1 moving arround a layer0 395 | 396 | void TripleMotion() { 397 | 398 | currentPalette = RainbowColors_p; 399 | colorshift++; 400 | noisesmoothing = 200; 401 | 402 | x[0] = 10 * beatsin(10, 0, 10000, 0); 403 | y[0] = 10 * beatsin(9, 0, 10000, 63); 404 | z[0] += 1000; 405 | scale_x[0] = 6000; 406 | scale_y[0] = 8000; 407 | FillNoise(0); 408 | 409 | x[1] = x[0] + (10 * beatsin(13, 0, 10000, 0)); 410 | y[1] = y[0] + (10 * beatsin(12, 0, 10000, 63)); 411 | z[1] += 1000; 412 | scale_x[1] = 6000; 413 | scale_y[1] = 8000; 414 | FillNoise(1); 415 | 416 | x[2] = x[1] + (10 * beatsin(18, 0, 10000, 0)); 417 | y[2] = y[1] + (10 * beatsin(17, 0, 10000, 63)); 418 | z[2] += 1000; 419 | scale_x[2] = 6000; 420 | scale_y[2] = 8000; 421 | FillNoise(2); 422 | 423 | MergeMethod4(2); 424 | //Show3Layers(); 425 | } 426 | 427 | 428 | // just shows the color gradient 429 | 430 | void ShowRedPalette() { 431 | PaletteRed(); 432 | ShowPalette(); 433 | } 434 | 435 | 436 | void CrossNoise() { 437 | 438 | currentPalette = RainbowStripeColors_p; 439 | colorshift = 50; 440 | noisesmoothing = 20; 441 | 442 | //x[0] = 10 * beatsin(10, 0, 10000, 0); 443 | y[0] += 100; 444 | z[0] += 50; 445 | scale_x[0] = 4000; 446 | scale_y[0] = 4000; 447 | FillNoise(0); 448 | byte border = beatsin8(10, 20, 236); 449 | 450 | CrossMapping(1, border); 451 | } 452 | 453 | 454 | void CrossNoise2() { 455 | 456 | currentPalette = RainbowStripeColors_p; 457 | noisesmoothing = 20; 458 | 459 | y[0] += 100; 460 | z[0] += 50; 461 | scale_x[0] = beatsin16(3,1000,10000); 462 | scale_y[0] = beatsin16(2,1000,10000); 463 | FillNoise(0); 464 | 465 | byte border = beatsin8(8); 466 | 467 | CrossMapping(1, border); 468 | } 469 | 470 | 471 | void RandomAnimation() { 472 | 473 | noisesmoothing = 100; 474 | 475 | // danger: dirty + crappy code! 476 | // use EVERY_N_MILLIS instead! 477 | byte ping=beatsin8(10); 478 | if (ping < 1) { 479 | SetupRandomPalette(); 480 | dy = random(2000) - 1000; 481 | dx = random(2000) - 1000; 482 | dz = random(2000) - 1000; 483 | scale_x[0] = random(8000) + 2000; 484 | scale_y[0] = random(8000) + 2000; 485 | } 486 | 487 | y[0] += dy; 488 | x[0] += dx; 489 | z[0] += dz; 490 | FillNoise(0); 491 | 492 | 493 | ShowLayer(0, 2); 494 | } 495 | 496 | 497 | 498 | void MilliTimer() { 499 | 500 | currentPalette = RainbowStripeColors_p; 501 | 502 | //EVERY_N_SECONDS(10) {colorshift += random8();} 503 | 504 | //colorshift= beatsin88(12, 0,255, 0,0); 505 | 506 | y[0] = millis()*spd; 507 | x[0] = 2*beatsin88(spd*256); 508 | scale_x[0] = 4000; 509 | scale_y[0] = 4000; 510 | y[1] = millis()*spd*2; 511 | x[1] = 2*beatsin88(spd*256); 512 | scale_x[1] = 4000; 513 | scale_y[1] = 4000; 514 | FillNoise(0); 515 | FillNoise(1); 516 | MergeMethod3(1); 517 | } 518 | 519 | 520 | void Caleido1() { 521 | 522 | EVERY_N_SECONDS(4) { 523 | 524 | SetupRandomPalette2(); 525 | dy = random16(4000) - 2000; 526 | dx = random16(4000) - 2000; 527 | dz = random16(4000) - 2000; 528 | scale_x[0] = random16(10000) + 2000; 529 | scale_y[0] = random16(10000) + 2000; 530 | } 531 | 532 | y[0] += dy; 533 | x[0] += dx; 534 | z[0] += dz; 535 | FillNoise(0); 536 | 537 | ShowLayer(0, 1); 538 | Caleidoscope2(); 539 | } 540 | 541 | 542 | void Caleido2() { 543 | 544 | EVERY_N_SECONDS(4) { 545 | 546 | SetupRandomPalette3(); 547 | dy = random16(4000) - 2000; 548 | dx = random16(4000) - 2000; 549 | dz = random16(4000) - 2000; 550 | scale_x[0] = random16(10000) + 2000; 551 | scale_y[0] = random16(10000) + 2000; 552 | } 553 | 554 | y[0] += dy; 555 | x[0] += dx; 556 | z[0] += dz; 557 | FillNoise(0); 558 | 559 | ShowLayer(0, 1); 560 | Caleidoscope1(); 561 | } 562 | 563 | 564 | // the "Electric Mandala" 565 | 566 | void Caleido3() { 567 | 568 | // a new parameter set every 15 seconds 569 | EVERY_N_SECONDS(15) { 570 | 571 | SetupRandomPalette3(); 572 | dy = random16(500) - 250; // random16(2000) - 1000 is pretty fast but works fine, too 573 | dx = random16(500) - 250; 574 | dz = random16(500) - 250; 575 | scale_x[0] = random16(10000) + 2000; 576 | scale_y[0] = random16(10000) + 2000; 577 | } 578 | 579 | y[0] += dy; 580 | x[0] += dx; 581 | z[0] += dz; 582 | 583 | FillNoise(0); 584 | ShowLayer(0, 1); 585 | 586 | Caleidoscope3(); 587 | Caleidoscope1(); 588 | } 589 | 590 | 591 | void Caleido4() { 592 | 593 | EVERY_N_SECONDS(45) { 594 | 595 | SetupRandomPalette3(); 596 | /* 597 | dy = random16(2000) - 1000; // random16(2000) - 1000 is pretty fast but works fine, too 598 | dx = random16(2000) - 1000; 599 | dz = random16(2000) - 1000; 600 | */ 601 | 602 | dy = random16(500) - 250; 603 | dx = random16(500) - 250; 604 | dz = random16(500) - 250; 605 | 606 | scale_x[0] = random16(10000) + 2000; 607 | scale_y[0] = random16(10000) + 2000; 608 | } 609 | 610 | y[0] += dy; 611 | x[0] += dx; 612 | z[0] += dz; 613 | 614 | FillNoise(0); 615 | ShowLayer(0, 1); 616 | 617 | Caleidoscope4(); 618 | Caleidoscope2(); 619 | } 620 | 621 | void Caleido5() { 622 | 623 | // a new parameter set every 10 seconds 624 | EVERY_N_SECONDS(10) { 625 | 626 | SetupRandomPalette4(); 627 | 628 | dy = random16(1000) - 500; // random16(2000) - 1000 is pretty fast but works fine, too 629 | dx = random16(1000) - 500; 630 | dz = random16(500); 631 | 632 | 633 | scale_x[0] = random16(7000) + 2000; 634 | scale_y[0] = random16(7000) + 2000; 635 | } 636 | 637 | y[0] += dy; 638 | x[0] += dx; 639 | z[0] += dz; 640 | 641 | EVERY_N_MILLIS(50) { 642 | colorshift++; 643 | } 644 | 645 | FillNoise(0); 646 | ShowLayer(0, 1); 647 | 648 | Caleidoscope5(); 649 | Caleidoscope4(); 650 | Caleidoscope2(); 651 | } 652 | 653 | 654 | void Caleido6() { 655 | 656 | // a new parameter set every 10 seconds 657 | EVERY_N_SECONDS(10) { 658 | 659 | SetupRandomPalette4(); 660 | 661 | dy = random16(1000) - 500; // random16(2000) - 1000 is pretty fast but works fine, too 662 | dx = random16(1000) - 500; 663 | dz = random16(500); 664 | 665 | 666 | scale_x[0] = random16(7000) + 2000; 667 | scale_y[0] = random16(7000) + 2000; 668 | } 669 | 670 | y[0] += dy; 671 | x[0] += dx; 672 | z[0] += dz; 673 | 674 | EVERY_N_MILLIS(50) { 675 | colorshift++; 676 | } 677 | 678 | FillNoise(0); 679 | ShowLayerBright(0, 1); 680 | 681 | //Caleidoscope5(); 682 | Caleidoscope4(); 683 | Caleidoscope1(); 684 | } 685 | 686 | 687 | void Caleido7() { 688 | 689 | EVERY_N_SECONDS(10) { 690 | 691 | SetupRandomPalette4(); 692 | 693 | dy = random16(1000) - 500; 694 | dx = random16(1000) - 500; 695 | dz = random16(500); 696 | 697 | 698 | scale_x[0] = random16(7000) + 2000; 699 | scale_y[0] = random16(7000) + 2000; 700 | } 701 | 702 | y[0] += dy; 703 | x[0] += dx; 704 | z[0] += dz; 705 | 706 | EVERY_N_MILLIS(50) { 707 | colorshift++; 708 | } 709 | 710 | FillNoise(0); 711 | ShowLayerBright(0, 1); 712 | 713 | Caleidoscope4(); 714 | Caleidoscope1(); 715 | FilterAll(); 716 | } 717 | 718 | -------------------------------------------------------------------------------- /DevelopmentTools.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Some useful functions for developing and debugging. 3 | Contains some magic numbers and is written specificly 4 | for the SmartMatrix. 5 | 6 | 7 | ----------------------------------------------------------------- 8 | */ 9 | 10 | 11 | // Show the current palette. 12 | 13 | void ShowPalette() { 14 | for(int i = 0; i < NUM_LEDS; i++) { 15 | byte color = i / (NUM_LEDS / 256); 16 | byte bri = 255; 17 | leds[i] = ColorFromPalette( currentPalette, color, bri ); 18 | } 19 | } 20 | 21 | 22 | // show just one layer 23 | 24 | void ShowLayer(byte layer, byte colorrepeat) { 25 | for(uint8_t i = 0; i < kMatrixWidth; i++) { 26 | for(uint8_t j = 0; j < kMatrixHeight; j++) { 27 | 28 | uint8_t color = noise[layer][i][j]; 29 | 30 | uint8_t bri = color; 31 | 32 | // assign a color depending on the actual palette 33 | CRGB pixel = ColorFromPalette( currentPalette, colorrepeat * (color + colorshift), bri ); 34 | 35 | leds[XY(i,j)] = pixel; 36 | } 37 | } 38 | } 39 | 40 | 41 | // map a layer while ignoring the brightness information and replacing it by maximum 42 | 43 | void ShowLayerBright(byte layer, byte colorrepeat) { 44 | for(uint8_t i = 0; i < kMatrixWidth; i++) { 45 | for(uint8_t j = 0; j < kMatrixHeight; j++) { 46 | 47 | uint8_t color = noise[layer][i][j]; 48 | 49 | uint8_t bri = 255; 50 | 51 | // assign a color depending on the actual palette 52 | CRGB pixel = ColorFromPalette( currentPalette, colorrepeat * (color + colorshift), bri ); 53 | 54 | leds[XY(i,j)] = pixel; 55 | } 56 | } 57 | } 58 | 59 | 60 | // Show 3 small 16x16 versions of the 3 noise planes 61 | // to keep track what is going on where when. 62 | // Useful to check before you start merging layers. 63 | // Expects a 32x32 matrix to be the output device. 64 | 65 | void Show3Layers() { 66 | for(uint8_t i = 0; i < 16; i++) { 67 | for(uint8_t j = 0; j < 16; j++) { 68 | leds[XY(i,j)] = ColorFromPalette( currentPalette, noise[0][i*2][j*2]*2 , 255 ); 69 | } 70 | } 71 | for(uint8_t i = 16; i < 32; i++) { 72 | for(uint8_t j = 0; j < 16; j++) { 73 | leds[XY(i,j)] = ColorFromPalette( currentPalette, noise[1][(i-16)*2][j*2]*2 , 255 ); 74 | } 75 | } 76 | for(uint8_t i = 0; i < 16; i++) { 77 | for(uint8_t j = 16; j < 32; j++) { 78 | leds[XY(i,j)] = ColorFromPalette( currentPalette, noise[2][i*2][(j-16)*2]*2 , 255 ); 79 | } 80 | } 81 | } 82 | 83 | // serial output parameters for debugging 84 | 85 | void ShowParameters(byte layer) { 86 | Serial.print("L"); 87 | Serial.print(layer); 88 | Serial.print(" "); 89 | Serial.print(x[layer]); 90 | Serial.print(" "); 91 | Serial.print(y[layer]); 92 | Serial.print(" "); 93 | Serial.print(z[layer]); 94 | Serial.print(" "); 95 | Serial.print(scale_x[layer]); 96 | Serial.print(" "); 97 | Serial.print(scale_y[layer]); 98 | Serial.print(" "); 99 | } 100 | 101 | // serial output the noise value of noise[layer][0][0] for debugging 102 | 103 | void SerialWriteNoiseValue(byte layer) { 104 | Serial.print("Layer"); 105 | Serial.print(layer); 106 | Serial.print(": "); 107 | Serial.print(noise[layer][0][0]); 108 | Serial.print(" "); 109 | } 110 | 111 | 112 | // serial output menu values for debugging 113 | 114 | void ShowMenuValues() { 115 | // serial print all relevant data 116 | Serial.print("Mode "); 117 | Serial.print(mode); 118 | Serial.print(" PGM "); 119 | Serial.print(pgm); 120 | Serial.print(" SPD "); 121 | Serial.print(spd); 122 | Serial.print(" BRI "); 123 | Serial.print(brightness); 124 | Serial.print(" RED "); 125 | Serial.print(red_level); 126 | Serial.print(" GRN "); 127 | Serial.print(green_level); 128 | Serial.print(" BLU "); 129 | Serial.print(blue_level); 130 | Serial.print(" FPS: "); 131 | Serial.println(LEDS.getFPS()); 132 | } 133 | 134 | 135 | // under construction! 136 | 137 | void ShowNumberDistribution() { 138 | currentPalette = RainbowColors_p; 139 | x[0] += 1000; 140 | y[0] += 1000; 141 | z[0] += 1000; 142 | FillNoise(0); 143 | CLS(); 144 | // clear array 145 | for(uint16_t i = 0; i < 256; i++) { 146 | values[i] = 0; 147 | } 148 | // count values 149 | for(uint16_t i = 0; i < 32; i++) { 150 | for(uint16_t j = 0; j < 32; j++) { 151 | //if (noise[0][i][j] == 133) values[0]++; 152 | //if (noise[0][i][j] == 129) values[1]++; 153 | values[noise[0][i][j]]++; 154 | } 155 | } 156 | // output a part of the result 157 | for(uint16_t i = 150; i < 170; i++) { 158 | Serial.print(" "); 159 | Serial.print(values[i]); 160 | } 161 | // draw chart 162 | for(uint8_t i = 100; i < 132; i++) { 163 | for(uint8_t j = 0; j < values[i]; j++) { 164 | leds[XY(i-100, 32-(j/4))] = 0xFF0000; 165 | } 166 | } 167 | } 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /FunkyNoise_SmartMatrix_Edition.ino: -------------------------------------------------------------------------------- 1 | /* 2 | FunkyNoise 1.0 3 | ---------------- 4 | A Collection Of 5 | Animations 6 | And Helper Functions 7 | 8 | for two dimensional led effects 9 | on the 32x32 SmartMatrix. 10 | 11 | Tested on PJRCs Teensy 3.1 @ 96Mhz. 12 | 13 | With explicit thanks to Daniel Garcia, 14 | Mark Kriegsmann and Louis Beaudoin. 15 | 16 | Written by Stefan Petrick 2014. 17 | 18 | hello(at) stefan-petrick . de 19 | 20 | ... 21 | 22 | Download the required software first: 23 | FastLED 3.0 24 | SmartMatrix 25 | Arduino IDE 1.0.6 26 | Teensyduino 1.2 27 | 28 | */ 29 | 30 | #include 31 | #include 32 | 33 | // the size of your matrix 34 | #define kMatrixWidth 32 35 | #define kMatrixHeight 32 36 | 37 | // used in FillNoise for central zooming 38 | byte CentreX = (kMatrixWidth / 2) - 1; 39 | byte CentreY = (kMatrixHeight / 2) - 1; 40 | 41 | // set up the framebuffer 42 | #define NUM_LEDS (kMatrixWidth * kMatrixHeight) 43 | CRGB leds[kMatrixWidth * kMatrixHeight]; 44 | 45 | // a place to store the color palette 46 | CRGBPalette16 currentPalette; 47 | 48 | // can be used for palette rotation 49 | // "colorshift" 50 | byte colorshift; 51 | 52 | // The coordinates for 3 16-bit noise spaces. 53 | #define NUM_LAYERS 3 54 | 55 | uint32_t x[NUM_LAYERS]; 56 | uint32_t y[NUM_LAYERS]; 57 | uint32_t z[NUM_LAYERS]; 58 | uint32_t scale_x[NUM_LAYERS]; 59 | uint32_t scale_y[NUM_LAYERS]; 60 | 61 | // used for the random based animations 62 | int16_t dx; 63 | int16_t dy; 64 | int16_t dz; 65 | int16_t dsx; 66 | int16_t dsy; 67 | 68 | // a 3dimensional array used to store the calculated 69 | // values of the different noise planes 70 | uint8_t noise[NUM_LAYERS][kMatrixWidth][kMatrixHeight]; 71 | 72 | // used for the color histogramm 73 | uint16_t values[256]; 74 | 75 | uint8_t noisesmoothing; 76 | 77 | // everything for the button + menu handling 78 | int button1; 79 | int button2; 80 | int button3; 81 | byte mode; 82 | byte pgm; 83 | byte spd; 84 | byte brightness; 85 | byte red_level; 86 | byte green_level; 87 | byte blue_level; 88 | 89 | 90 | void setup() { 91 | 92 | // enable debugging info output 93 | Serial.begin(115200); 94 | 95 | // add the SmartMatrix controller 96 | LEDS.addLeds(leds,NUM_LEDS); 97 | 98 | // switch dithering off to avoid flicking at low fps 99 | FastLED.setDither(0); 100 | 101 | // adjust the gamma curves to human perception 102 | pSmartMatrix->setColorCorrection(cc48); 103 | 104 | // fill all animation variables with valid values to 105 | // allow straight forward animation programming 106 | BasicVariablesSetup(); 107 | 108 | // the pins for the 3 buttons of my custom interface 109 | pinMode(17, INPUT); 110 | pinMode(18, INPUT); 111 | pinMode(19, INPUT); 112 | 113 | SetupMatrixText(); 114 | } 115 | 116 | 117 | // basically beatsin16 with an additional phase 118 | 119 | uint16_t beatsin(accum88 beats_per_minute, uint16_t lowest = 0, uint16_t highest = 65535, byte phase = 0) 120 | { 121 | uint16_t beat = beat16( beats_per_minute); 122 | uint16_t beatsin = (sin16( beat+(phase*256)) + 32768); 123 | uint16_t rangewidth = highest - lowest; 124 | uint16_t scaledbeat = scale16( beatsin, rangewidth); 125 | uint16_t result = lowest + scaledbeat; 126 | return result; 127 | } 128 | 129 | void loop() { 130 | 131 | /* 132 | Whats new? 133 | Caleidoscope1-5 functions in experimental.ino 134 | Calceidoscope examples Caleido1-7 in Animations.ino 135 | */ 136 | 137 | Caleido3(); 138 | ShowFrame(); 139 | 140 | } 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /HelperFunctions.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Helpfull functions to keep the actual animation code short. 3 | Contains so far: 4 | 5 | XY() 6 | FillNoise(byte layer) 7 | BasicVariablesSetup 8 | ShowFrame 9 | DimAll(byte value) 10 | CLS 11 | MergeMethod1(byte colorrepeat) 12 | MergeMethod2(byte colorrepeat) 13 | MergeMethod3(byte colorrepeat) 14 | MergeMethod4(byte colorrepeat) 15 | ConstrainedMapping(byte layer, byte lower_limit, byte upper_limit, byte colorrepeat) 16 | ShowAll(uint16_t frames_per_animation) 17 | ColorCorrection 18 | 19 | (uncomplete list) 20 | 21 | ----------------------------------------------------------------- 22 | */ 23 | 24 | 25 | // Translate the x/y coordinates into the right index in the 26 | // framebuffer. 27 | // The Smartmatrix has a simple line by line layout, no 28 | // serpentines. It safed 2 fps to keep this function short. 29 | // The function is called (sometimes) over 200 000 times per second! 30 | 31 | uint16_t XY( uint8_t x, uint8_t y) { 32 | uint16_t i; 33 | i = (y * kMatrixWidth) + x; 34 | return i; 35 | } 36 | 37 | 38 | // Fill the x/y array with 16-bit noise values 39 | 40 | void FillNoise(byte layer) { 41 | 42 | for(uint8_t i = 0; i < kMatrixWidth; i++) { 43 | 44 | uint32_t ioffset = scale_x[layer] * (i-CentreX); 45 | 46 | for(uint8_t j = 0; j < kMatrixHeight; j++) { 47 | 48 | uint32_t joffset = scale_y[layer] * (j-CentreY); 49 | 50 | byte data = inoise16(x[layer] + ioffset, y[layer] + joffset, z[layer]) >> 8; 51 | 52 | uint8_t olddata = noise[layer][i][j]; 53 | uint8_t newdata = scale8( olddata, noisesmoothing ) + scale8( data, 256 - noisesmoothing ); 54 | data = newdata; 55 | 56 | 57 | noise[layer][i][j] = data; 58 | } 59 | } 60 | } 61 | 62 | 63 | // Initialise the coordinates of the noise space with random 64 | // values for an altering starting point. 65 | // Set the zoom factor to a moderate level. 66 | // Fill the delta values with random stepwidths. 67 | 68 | void BasicVariablesSetup() { 69 | 70 | // set to reasonable values to avoid a black out 71 | colorshift = 0; 72 | noisesmoothing = 200; 73 | 74 | currentPalette = RainbowStripeColors_p; 75 | 76 | 77 | // just any free input pin 78 | random16_add_entropy(analogRead(18)); 79 | 80 | // fill coordinates with random values 81 | // set zoom levels 82 | for(int i = 0; i < NUM_LAYERS; i++) { 83 | x[i] = random16(); 84 | y[i] = random16(); 85 | z[i] = random16(); 86 | scale_x[i] = 6000; 87 | scale_y[i] = 6000; 88 | } 89 | // for the random movement 90 | dx = random8(); 91 | dy = random8(); 92 | dz = random8(); 93 | dsx = random8(); 94 | dsy = random8(); 95 | 96 | // everything for the menu 97 | mode = 0; 98 | spd = 10; 99 | brightness = 255; 100 | red_level = 255; 101 | green_level = 255; 102 | blue_level = 255; 103 | 104 | LEDS.setBrightness(brightness); 105 | } 106 | 107 | 108 | // Update leds and show fps 109 | 110 | void ShowFrame() { 111 | 112 | // update leds 113 | LEDS.show(); 114 | 115 | // count and output the fps 116 | LEDS.countFPS(); 117 | 118 | // output debugging infos 119 | ShowMenuValues(); 120 | } 121 | 122 | 123 | // Dim everything in leds a bit down. 124 | 125 | void DimAll(byte value) 126 | { 127 | for(int i = 0; i < NUM_LEDS; i++) { 128 | leds[i].nscale8(value); 129 | } 130 | } 131 | 132 | 133 | // Delete the leds array. 134 | 135 | void CLS() 136 | { 137 | for(int i = 0; i < NUM_LEDS; i++) { 138 | leds[i] = 0; 139 | } 140 | } 141 | 142 | 143 | // overlay layers 0&1&2 for color, layer 2 is brightness 144 | 145 | void MergeMethod1(byte colorrepeat) { 146 | for(uint8_t i = 0; i < kMatrixWidth; i++) { 147 | for(uint8_t j = 0; j < kMatrixHeight; j++) { 148 | 149 | uint8_t color = ( ( noise[0][i][j] ) 150 | + ( noise[1][i][j] ) 151 | + ( noise[2][i][j] ) ) 152 | / 3; 153 | 154 | // layer 2 gives the brightness 155 | uint8_t bri = (noise[2][i][j]); 156 | 157 | // assign a color depending on the actual palette 158 | CRGB pixel = ColorFromPalette( currentPalette, colorrepeat * (color + colorshift), bri ); 159 | 160 | leds[XY(i,j)] = pixel; 161 | } 162 | } 163 | } 164 | 165 | 166 | // overlay layers 0&1 for color, layer 2 is brightness 167 | 168 | void MergeMethod2(byte colorrepeat) { 169 | for(uint8_t i = 0; i < kMatrixWidth; i++) { 170 | for(uint8_t j = 0; j < kMatrixHeight; j++) { 171 | 172 | // map the noise values down to a byte range 173 | // layer 0 and 2 interfere for the color 174 | uint8_t color = ( ( noise[0][i][j] ) 175 | + ( noise[1][i][j] ) ) 176 | / 2; 177 | 178 | // layer 2 gives the brightness 179 | uint8_t bri = (noise[2][i][j]); 180 | 181 | // assign a color depending on the actual palette 182 | CRGB pixel = ColorFromPalette( currentPalette, colorrepeat * (color + colorshift), bri ); 183 | 184 | leds[XY(i,j)] = pixel; 185 | } 186 | } 187 | } 188 | 189 | 190 | // overlay layers 0&1 for color, brightness is layer1 191 | 192 | void MergeMethod3(byte colorrepeat) { 193 | for(uint8_t i = 0; i < kMatrixWidth; i++) { 194 | for(uint8_t j = 0; j < kMatrixHeight; j++) { 195 | 196 | // map the noise values down to a byte range 197 | // layer 0 and 2 interfere for the color 198 | uint8_t color = ( ( noise[0][i][j] ) 199 | + ( noise[1][i][j] ) ) 200 | / 2; 201 | 202 | // layer 1 gives the brightness 203 | uint8_t bri = noise[1][i][j]; 204 | 205 | // assign a color depending on the actual palette 206 | CRGB pixel = ColorFromPalette( currentPalette, colorrepeat * (color + colorshift), bri ); 207 | 208 | leds[XY(i,j)] = pixel; 209 | } 210 | } 211 | } 212 | 213 | 214 | // overlay layers 0&1&2 for color, layer 0 is brightness 215 | 216 | void MergeMethod4(byte colorrepeat) { 217 | for(uint8_t i = 0; i < kMatrixWidth; i++) { 218 | for(uint8_t j = 0; j < kMatrixHeight; j++) { 219 | 220 | uint8_t color = ( ( noise[0][i][j] ) 221 | + ( noise[1][i][j] ) 222 | + ( noise[2][i][j] ) ) 223 | / 3; 224 | 225 | uint8_t bri = (noise[0][i][j]); 226 | 227 | // assign a color depending on the actual palette 228 | CRGB pixel = ColorFromPalette( currentPalette, colorrepeat * (color + colorshift), bri ); 229 | 230 | leds[XY(i,j)] = pixel; 231 | } 232 | } 233 | } 234 | 235 | 236 | // draw the part between lower and upper limit of one layer 237 | 238 | void ConstrainedMapping(byte layer, byte lower_limit, byte upper_limit, byte colorrepeat) { 239 | 240 | for(uint8_t i = 0; i < kMatrixWidth; i++) { 241 | for(uint8_t j = 0; j < kMatrixHeight; j++) { 242 | 243 | uint8_t data = noise[layer][i][j] ; 244 | 245 | if ( data >= lower_limit && data <= upper_limit) { 246 | 247 | CRGB pixel = ColorFromPalette( currentPalette, colorrepeat * (data + colorshift), data ); 248 | 249 | leds[XY(i,j)] = pixel; 250 | } 251 | } 252 | } 253 | } 254 | 255 | 256 | // one possibility for a basic scripting / frame line composition 257 | 258 | void ShowAll(uint16_t count) { 259 | for(uint16_t i = 0; i < count; i++) { 260 | MirroredNoise(); 261 | ShowFrame(); 262 | } 263 | 264 | for(uint16_t i = 0; i < count; i++) { 265 | RedClouds(); 266 | ShowFrame(); 267 | } 268 | 269 | for(uint16_t i = 0; i < count; i++) { 270 | Lavalamp1(); 271 | ShowFrame(); 272 | } 273 | 274 | for(uint16_t i = 0; i < count; i++) { 275 | Lavalamp2(); 276 | ShowFrame(); 277 | } 278 | 279 | for(uint16_t i = 0; i < count; i++) { 280 | Lavalamp3(); 281 | ShowFrame(); 282 | } 283 | 284 | 285 | for(uint16_t i = 0; i < count; i++) { 286 | Lavalamp4(); 287 | ShowFrame(); 288 | } 289 | 290 | for(uint16_t i = 0; i < count; i++) { 291 | Lavalamp5(); 292 | ShowFrame(); 293 | } 294 | 295 | for(uint16_t i = 0; i < count; i++) { 296 | Constrained1(); 297 | ShowFrame(); 298 | } 299 | 300 | for(uint16_t i = 0; i < count; i++) { 301 | RelativeMotion1(); 302 | ShowFrame(); 303 | } 304 | 305 | for(uint16_t i = 0; i < count; i++) { 306 | Water(); 307 | ShowFrame(); 308 | } 309 | 310 | for(uint16_t i = 0; i < count; i++) { 311 | Bubbles1(); 312 | ShowFrame(); 313 | } 314 | 315 | for(uint16_t i = 0; i < count; i++) { 316 | TripleMotion(); 317 | ShowFrame(); 318 | } 319 | 320 | for(uint16_t i = 0; i < count; i++) { 321 | CrossNoise2(); 322 | ShowFrame(); 323 | } 324 | } 325 | 326 | 327 | // allows to dim colors down 328 | // works on the screenbuffer, after the image is computed 329 | 330 | void ColorCorrection() { 331 | for(uint16_t i = 0; i < NUM_LEDS; i++) { 332 | leds[i].r = scale8(leds[i].r, red_level); 333 | leds[i].g = scale8(leds[i].g, green_level); 334 | leds[i].b = scale8(leds[i].b, blue_level); 335 | } 336 | } 337 | 338 | 339 | // a constrained noise the fills the holes with a mirrored and recolored version of the same noise 340 | 341 | void CrossMapping(byte colorrepeat, byte limit) { 342 | for(uint8_t i = 0; i < kMatrixWidth; i++) { 343 | for(uint8_t j = 0; j < kMatrixHeight; j++) { 344 | 345 | uint8_t color1 = noise[0][i][j]; 346 | uint8_t color2 = noise[0][j][i]; 347 | 348 | CRGB pixel; 349 | 350 | if (color1 > limit) { 351 | pixel = ColorFromPalette( currentPalette, colorrepeat * (color1 + colorshift), color2 ); 352 | } 353 | else { 354 | pixel = ColorFromPalette( currentPalette, colorrepeat * (color2 + colorshift + 128), color1 ); 355 | } 356 | leds[XY(i,j)] = pixel; 357 | } 358 | } 359 | } 360 | 361 | 362 | // a brightness mask based on layer 0 for the complete screenbuffer 363 | 364 | void FilterAll() { 365 | for(uint8_t i = 0; i < kMatrixWidth; i++) { 366 | for(uint8_t j = 0; j < kMatrixHeight; j++) { 367 | leds[XY(i,j)] %= noise[0][i][j]; 368 | } 369 | } 370 | } 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Stefan Petrick 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Menu.ino: -------------------------------------------------------------------------------- 1 | // Some functions only used by my custom 3 button user interface. 2 | // You might never need it. 3 | 4 | 5 | void RunAnimationDependingOnPgm() { 6 | switch (pgm) { 7 | 8 | case 0: 9 | MirroredNoise(); 10 | break; 11 | 12 | case 1: 13 | RedClouds(); 14 | break; 15 | 16 | case 2: 17 | Lavalamp1(); 18 | break; 19 | 20 | case 3: 21 | Lavalamp2(); 22 | break; 23 | 24 | case 4: 25 | Lavalamp3(); 26 | break; 27 | 28 | case 5: 29 | Lavalamp4(); 30 | break; 31 | 32 | case 6: 33 | Lavalamp5(); 34 | break; 35 | 36 | case 7: 37 | Constrained1(); 38 | break; 39 | 40 | case 8: 41 | RelativeMotion1(); 42 | break; 43 | 44 | case 9: 45 | Water(); 46 | break; 47 | 48 | case 10: 49 | Bubbles1(); 50 | break; 51 | 52 | case 11: 53 | TripleMotion(); 54 | break; 55 | 56 | case 12: 57 | CrossNoise(); 58 | break; 59 | 60 | case 13: 61 | CrossNoise2(); 62 | break; 63 | 64 | case 14: 65 | RandomAnimation(); 66 | break; 67 | 68 | case 15: 69 | MilliTimer(); 70 | break; 71 | 72 | case 16: 73 | Caleido1(); 74 | break; 75 | 76 | case 17: 77 | Caleido2(); 78 | break; 79 | 80 | case 18: 81 | Caleido3(); 82 | break; 83 | 84 | case 19: 85 | Caleido5(); 86 | break; 87 | } 88 | } 89 | 90 | void ReadButtons () { 91 | byte NUM_PGM = 19; 92 | byte DEBOUNCE_DELAY = 200; 93 | byte STEP_WIDTH = 64; 94 | button1 = digitalRead(17); 95 | button2 = digitalRead(18); 96 | button3 = digitalRead(19); 97 | 98 | // if any button pressed 99 | if (button1 == LOW || button2 == LOW || button3 == LOW) { 100 | 101 | if (button1 == LOW) { // change (increment) mode 102 | mode ++; 103 | if (mode == 7) mode = 0; 104 | switch (mode) { 105 | 106 | case 0: 107 | pSmartMatrix->scrollText("PROGAM + -", -1); 108 | break; 109 | 110 | case 1: 111 | pSmartMatrix->scrollText("SPEED + -", -1); 112 | break; 113 | 114 | case 2: 115 | pSmartMatrix->scrollText("BRIGHTNESS + -", -1); 116 | break; 117 | 118 | case 3: 119 | pSmartMatrix->scrollText("RED + -", -1); 120 | break; 121 | 122 | case 4: 123 | pSmartMatrix->scrollText("GREEN + -", -1); 124 | break; 125 | 126 | case 5: 127 | pSmartMatrix->scrollText("BLUE + -", -1); 128 | break; 129 | 130 | case 6: 131 | pSmartMatrix->scrollText("+ FOR RESET - FOR TEXT OFF", -1); 132 | break; 133 | 134 | } 135 | 136 | delay(DEBOUNCE_DELAY); 137 | // 0 pgm 138 | // 1 spd 139 | // 2 bri 140 | // 3 red 141 | // 4 green 142 | // 5 blue 143 | // 6 reset 144 | 145 | } 146 | 147 | if (mode == 0 && button2 == LOW) { // pgm up 148 | pgm++; 149 | delay(DEBOUNCE_DELAY); 150 | if (pgm == NUM_PGM+1) pgm = 0; 151 | } 152 | if (mode == 0 && button3 == LOW) { // pgm down 153 | pgm--; 154 | delay(DEBOUNCE_DELAY); 155 | if (pgm == 255) pgm = NUM_PGM; 156 | } 157 | if (mode == 1 && button2 == LOW) { // spd up 158 | spd+=10; 159 | delay(DEBOUNCE_DELAY); 160 | } 161 | if (mode == 1 && button3 == LOW) { // spd down 162 | spd-=10; 163 | delay(DEBOUNCE_DELAY); 164 | } 165 | if (mode == 2 && button2 == LOW) { // bri up 166 | brightness = brightness + STEP_WIDTH; 167 | LEDS.setBrightness(brightness); 168 | delay(DEBOUNCE_DELAY); 169 | } 170 | if (mode == 2 && button3 == LOW) { // bri down 171 | brightness = brightness - STEP_WIDTH; 172 | LEDS.setBrightness(brightness); 173 | delay(DEBOUNCE_DELAY); 174 | } 175 | if (mode == 3 && button2 == LOW) { // red up 176 | red_level = red_level + STEP_WIDTH; 177 | delay(DEBOUNCE_DELAY); 178 | } 179 | if (mode == 3 && button3 == LOW) { // red down 180 | red_level = red_level - STEP_WIDTH; 181 | delay(DEBOUNCE_DELAY); 182 | } 183 | if (mode == 4 && button2 == LOW) { // green up 184 | green_level = green_level + STEP_WIDTH; 185 | delay(DEBOUNCE_DELAY); 186 | } 187 | if (mode == 4 && button3 == LOW) { // green down 188 | green_level = green_level - STEP_WIDTH; 189 | delay(DEBOUNCE_DELAY); 190 | } 191 | if (mode == 5 && button2 == LOW) { // blue up 192 | blue_level = blue_level + STEP_WIDTH; 193 | delay(DEBOUNCE_DELAY); 194 | } 195 | if (mode == 5 && button3 == LOW) { // blue down 196 | blue_level = blue_level - STEP_WIDTH; 197 | delay(DEBOUNCE_DELAY); 198 | } 199 | if (mode == 6 && button2 == LOW) { // reset all 200 | BasicVariablesSetup(); 201 | delay(DEBOUNCE_DELAY); 202 | } 203 | if (mode == 6 && button3 == LOW) { // reset text 204 | pSmartMatrix->scrollText(" ", -1); 205 | delay(DEBOUNCE_DELAY); 206 | } 207 | } 208 | } 209 | 210 | void SetupMatrixText() { 211 | pSmartMatrix->setScrollMode(wrapForward); 212 | //pSmartMatrix->setScrollMode(stopped); 213 | pSmartMatrix->setScrollColor({ 214 | 0xff, 0xff, 0xff } 215 | ); 216 | pSmartMatrix->setScrollSpeed(35); 217 | pSmartMatrix->setScrollFont(font5x7); 218 | //pSmartMatrix->scrollText("FunkyNoise", -1); 219 | //pSmartMatrix->setScrollOffsetFromEdge(10); 220 | } 221 | 222 | 223 | void RunButtonMenu() { 224 | ReadButtons(); 225 | RunAnimationDependingOnPgm(); 226 | ColorCorrection(); 227 | ShowFrame(); 228 | } 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | -------------------------------------------------------------------------------- /Palettes.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Some color palettes. 3 | Includes the predifined FastLED palettes and custom ones. 4 | 5 | ----------------------------------------------------------------- 6 | */ 7 | 8 | 9 | // A red-black palette. 10 | 11 | void PaletteRed() { 12 | currentPalette = CRGBPalette16( 13 | CHSV( 0, 255, 255 ), 14 | CHSV( 0, 255, 0 ), 15 | CHSV( 0, 255, 0 ), 16 | CHSV( 0, 255, 255)); 17 | } 18 | 19 | 20 | void PaletteCustom() { 21 | currentPalette = CRGBPalette16( 22 | CHSV( 40, 255, 255), 23 | CHSV( 40, 255, 255), 24 | CHSV( 0, 255, 0 ), 25 | CHSV( 0, 255, 255)); 26 | } 27 | 28 | // Set here a global color palette. 29 | // All the the predifined FastLED palettes: 30 | 31 | void Pal() { 32 | //PaletteRed(); 33 | //PaletteCustom(); 34 | //currentPalette = CloudColors_p; 35 | //currentPalette = LavaColors_p; 36 | //currentPalette = OceanColors_p; 37 | currentPalette = ForestColors_p; 38 | //currentPalette = RainbowColors_p; 39 | //currentPalette = RainbowStripeColors_p; 40 | //currentPalette = PartyColors_p; 41 | //currentPalette = HeatColors_p; 42 | } 43 | 44 | 45 | void SetupRandomPalette() { 46 | currentPalette = CRGBPalette16( 47 | CHSV( random8(), 255, 32 ), 48 | CHSV( random8(), 255, 255), 49 | CHSV( random8(), 128, 255), 50 | CHSV( random8(), 255, 255)); 51 | } 52 | 53 | 54 | void Palette16() { 55 | currentPalette = CRGBPalette16( 56 | 0x000000, 0xFF0000, 0xFF0000, 0x000000, 57 | 0x000000, 0x00FF00, 0x00FF00, 0x000000, 58 | 0x000000, 0x0000FF, 0x0000FF, 0x000000, 59 | 0x000000, 0xFF0000, 0xFF0000, 0x000000); 60 | } 61 | 62 | 63 | void SetupRandomPalette2() { 64 | currentPalette = CRGBPalette16( 65 | CHSV( random8(), 255, 0 ), 66 | CHSV( random8(), 255, 0), 67 | CHSV( random8(), 255, 0), 68 | CHSV( random8(), 255, 0), 69 | 70 | CHSV( random8(), 255, random8() ), 71 | CHSV( random8(), random8(), 255), 72 | CHSV( random8(), 255, 255), 73 | CHSV( random8(), 255, 255), 74 | 75 | CHSV( random8(), 255, 0 ), 76 | CHSV( random8(), 255, 255), 77 | CHSV( random8(), 255, 255), 78 | CHSV( random8(), random8(), 255), 79 | 80 | CHSV( random8(), 255, 0 ), 81 | CHSV( random8(), 255, 0), 82 | CHSV( random8(), 255, 0), 83 | CHSV( random8(), 255, 0)); 84 | } 85 | 86 | 87 | void SetupRandomPalette3() { 88 | currentPalette = CRGBPalette16( 89 | CHSV( random8(), 255, 0 ), 90 | CHSV( random8(), 255, 0), 91 | CHSV( random8(), 255, 255), 92 | CHSV( random8(), 255, 255), 93 | 94 | CHSV( random8(), 255, 0 ), 95 | CHSV( random8(), 255, 255), 96 | CHSV( random8(), 255, 255), 97 | CHSV( random8(), 255, 0), 98 | 99 | CHSV( random8(), 255, 0 ), 100 | CHSV( random8(), 255, 255), 101 | CHSV( random8(), 255, 255), 102 | CHSV( random8(), 255, 0), 103 | 104 | CHSV( random8(), 255, 255 ), 105 | CHSV( random8(), 255, 255), 106 | CHSV( random8(), 255, 0), 107 | CHSV( random8(), 255, 0)); 108 | } 109 | 110 | 111 | void SetupRandomPalette4() { 112 | currentPalette = CRGBPalette16( 113 | CHSV( random8(), 255, random8() ), 114 | CHSV( random8(), 255, random8()), 115 | CHSV( random8(), 255, 0), 116 | CHSV( random8(), 255, 255), 117 | 118 | CHSV( random8(), 255, random8() ), 119 | CHSV( random8(), 255, 255), 120 | CHSV( random8(), 255, 255), 121 | CHSV( random8(), random8(), random8()), 122 | 123 | CHSV( random8(), 255, random8() ), 124 | CHSV( random8(), 255, 255), 125 | CHSV( random8(), 255, 0), 126 | CHSV( random8(), 255, random8()), 127 | 128 | CHSV( random8(), 255, 255 ), 129 | CHSV( random8(), 255, 0), 130 | CHSV( random8(), 255, 255), 131 | CHSV( random8(), 255, random8())); 132 | } 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FunkyNoise 1.0 2 | 3 | A collection of animations and helper functions for two dimensional led effects on the 32x32 SmartMatrix. 4 | Contains many examples demonstarting the usage of the functions. 5 | 6 | Tested on PJRCs Teensy 3.1 @ 96Mhz. 7 | 8 | With explicit thanks to Daniel Garcia, Mark Kriegsmann and Louis Beaudoin. 9 | 10 | Written by Stefan Petrick 2014. hello(at) stefan-petrick . de 11 | 12 | Please install the latest version of FastLED 3.1 first. 13 | https://github.com/FastLED/FastLED/tree/FastLED3.1 14 | -------------------------------------------------------------------------------- /experimental.ino: -------------------------------------------------------------------------------- 1 | // some stuff which has to prove if its worth to become part of FunkyNoise 2 | 3 | 4 | // a try to output a variable onto the SmartMatrix 5 | 6 | void PrintValue() { 7 | pSmartMatrix->swapBuffers(true); 8 | char value[3]; 9 | value[0] = '0' + brightness / 100; 10 | value[1] = '0' + (brightness % 100) / 10; 11 | value[2] = '0' + brightness % 10; 12 | pSmartMatrix->drawString(0, 16, { 13 | 200, 200, 200 } 14 | , value); 15 | pSmartMatrix->swapBuffers(true); 16 | delay(500); 17 | } 18 | 19 | 20 | // All the caleidoscope functions work directly within the screenbuffer (leds array). 21 | // Draw whatever you like in the area x(0-15) and y (0-15) and then copy it arround. 22 | 23 | // rotates the first 16x16 quadrant 3 times onto a 32x32 (+90 degrees rotation for each one) 24 | 25 | void Caleidoscope1() { 26 | for(int x = 0; x < kMatrixWidth / 2 ; x++) { 27 | for(int y = 0; y < kMatrixHeight / 2; y++) { 28 | leds[XY( kMatrixWidth - 1 - x, y )] = leds[XY( y, x )]; 29 | leds[XY( kMatrixWidth - 1 - x, kMatrixHeight - 1 - y )] = leds[XY( x, y )]; 30 | leds[XY( x, kMatrixHeight - 1 - y )] = leds[XY( y, x )]; 31 | } 32 | } 33 | } 34 | 35 | 36 | // mirror the first 16x16 quadrant 3 times onto a 32x32 37 | 38 | void Caleidoscope2() { 39 | for(int x = 0; x < kMatrixWidth / 2 ; x++) { 40 | for(int y = 0; y < kMatrixHeight / 2; y++) { 41 | leds[XY( kMatrixWidth - 1 - x, y )] = leds[XY( x, y )]; 42 | leds[XY( x, kMatrixHeight - 1 - y )] = leds[XY( x, y )]; 43 | leds[XY( kMatrixWidth - 1 - x, kMatrixHeight - 1 - y )] = leds[XY( x, y )]; 44 | } 45 | } 46 | } 47 | 48 | 49 | // copy one diagonal triangle into the other one within a 16x16 50 | 51 | void Caleidoscope3() { 52 | for(int x = 0; x <= CentreX ; x++) { 53 | for(int y = 0; y <= x; y++) { 54 | leds[XY( x, y )] = leds[XY( y, x )]; 55 | } 56 | } 57 | } 58 | 59 | 60 | // copy one diagonal triangle into the other one within a 16x16 (90 degrees rotated compared to Caleidoscope3) 61 | 62 | void Caleidoscope4() { 63 | for(int x = 0; x <= CentreX ; x++) { 64 | for(int y = 0; y <= CentreY-x; y++) { 65 | leds[XY( CentreY - y, CentreX - x )] = leds[XY( x, y )]; 66 | } 67 | } 68 | } 69 | 70 | 71 | // copy one diagonal triangle into the other one within a 8x8 72 | 73 | void Caleidoscope5() { 74 | for(int x = 0; x < kMatrixWidth/4 ; x++) { 75 | for(int y = 0; y <= x; y++) { 76 | leds[XY( x, y )] = leds[XY( y, x )]; 77 | } 78 | } 79 | 80 | for(int x = kMatrixWidth/4; x < kMatrixWidth/2 ; x++) { 81 | for(int y = kMatrixHeight/4; y >= 0; y--) { 82 | leds[XY( x, y )] = leds[XY( y, x )]; 83 | } 84 | } 85 | } 86 | 87 | 88 | 89 | 90 | --------------------------------------------------------------------------------