PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
5.6KB

  1. //
  2. // "Pacifica"
  3. // Gentle, blue-green ocean waves.
  4. // December 2019, Mark Kriegsman and Mary Corey March.
  5. // For Dan.
  6. //
  7. #define FASTLED_ALLOW_INTERRUPTS 0
  8. #include <FastLED.h>
  9. FASTLED_USING_NAMESPACE
  10. #define DATA_PIN 3
  11. #define NUM_LEDS 60
  12. #define MAX_POWER_MILLIAMPS 500
  13. #define LED_TYPE WS2812B
  14. #define COLOR_ORDER GRB
  15. //////////////////////////////////////////////////////////////////////////
  16. CRGB leds[NUM_LEDS];
  17. void setup() {
  18. delay( 3000); // 3 second delay for boot recovery, and a moment of silence
  19. FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS)
  20. .setCorrection( TypicalLEDStrip );
  21. FastLED.setMaxPowerInVoltsAndMilliamps( 5, MAX_POWER_MILLIAMPS);
  22. }
  23. void loop()
  24. {
  25. EVERY_N_MILLISECONDS( 20) {
  26. pacifica_loop();
  27. FastLED.show();
  28. }
  29. }
  30. //////////////////////////////////////////////////////////////////////////
  31. //
  32. // The code for this animation is more complicated than other examples, and
  33. // while it is "ready to run", and documented in general, it is probably not
  34. // the best starting point for learning. Nevertheless, it does illustrate some
  35. // useful techniques.
  36. //
  37. //////////////////////////////////////////////////////////////////////////
  38. //
  39. // In this animation, there are four "layers" of waves of light.
  40. //
  41. // Each layer moves independently, and each is scaled separately.
  42. //
  43. // All four wave layers are added together on top of each other, and then
  44. // another filter is applied that adds "whitecaps" of brightness where the
  45. // waves line up with each other more. Finally, another pass is taken
  46. // over the led array to 'deepen' (dim) the blues and greens.
  47. //
  48. // The speed and scale and motion each layer varies slowly within independent
  49. // hand-chosen ranges, which is why the code has a lot of low-speed 'beatsin8' functions
  50. // with a lot of oddly specific numeric ranges.
  51. //
  52. // These three custom blue-green color palettes were inspired by the colors found in
  53. // the waters off the southern coast of California, https://goo.gl/maps/QQgd97jjHesHZVxQ7
  54. //
  55. CRGBPalette16 pacifica_palette_1 =
  56. { 0x000507, 0x000409, 0x00030B, 0x00030D, 0x000210, 0x000212, 0x000114, 0x000117,
  57. 0x000019, 0x00001C, 0x000026, 0x000031, 0x00003B, 0x000046, 0x14554B, 0x28AA50 };
  58. CRGBPalette16 pacifica_palette_2 =
  59. { 0x000507, 0x000409, 0x00030B, 0x00030D, 0x000210, 0x000212, 0x000114, 0x000117,
  60. 0x000019, 0x00001C, 0x000026, 0x000031, 0x00003B, 0x000046, 0x0C5F52, 0x19BE5F };
  61. CRGBPalette16 pacifica_palette_3 =
  62. { 0x000208, 0x00030E, 0x000514, 0x00061A, 0x000820, 0x000927, 0x000B2D, 0x000C33,
  63. 0x000E39, 0x001040, 0x001450, 0x001860, 0x001C70, 0x002080, 0x1040BF, 0x2060FF };
  64. void pacifica_loop()
  65. {
  66. // Increment the four "color index start" counters, one for each wave layer.
  67. // Each is incremented at a different speed, and the speeds vary over time.
  68. static uint16_t sCIStart1, sCIStart2, sCIStart3, sCIStart4;
  69. static uint32_t sLastms = 0;
  70. uint32_t ms = GET_MILLIS();
  71. uint32_t deltams = ms - sLastms;
  72. sLastms = ms;
  73. uint16_t speedfactor1 = beatsin16(3, 179, 269);
  74. uint16_t speedfactor2 = beatsin16(4, 179, 269);
  75. uint32_t deltams1 = (deltams * speedfactor1) / 256;
  76. uint32_t deltams2 = (deltams * speedfactor2) / 256;
  77. uint32_t deltams21 = (deltams1 + deltams2) / 2;
  78. sCIStart1 += (deltams1 * beatsin88(1011,10,13));
  79. sCIStart2 -= (deltams21 * beatsin88(777,8,11));
  80. sCIStart3 -= (deltams1 * beatsin88(501,5,7));
  81. sCIStart4 -= (deltams2 * beatsin88(257,4,6));
  82. // Clear out the LED array to a dim background blue-green
  83. fill_solid( leds, NUM_LEDS, CRGB( 2, 6, 10));
  84. // Render each of four layers, with different scales and speeds, that vary over time
  85. pacifica_one_layer( pacifica_palette_1, sCIStart1, beatsin16( 3, 11 * 256, 14 * 256), beatsin8( 10, 70, 130), 0-beat16( 301) );
  86. pacifica_one_layer( pacifica_palette_2, sCIStart2, beatsin16( 4, 6 * 256, 9 * 256), beatsin8( 17, 40, 80), beat16( 401) );
  87. pacifica_one_layer( pacifica_palette_3, sCIStart3, 6 * 256, beatsin8( 9, 10,38), 0-beat16(503));
  88. pacifica_one_layer( pacifica_palette_3, sCIStart4, 5 * 256, beatsin8( 8, 10,28), beat16(601));
  89. // Add brighter 'whitecaps' where the waves lines up more
  90. pacifica_add_whitecaps();
  91. // Deepen the blues and greens a bit
  92. pacifica_deepen_colors();
  93. }
  94. // Add one layer of waves into the led array
  95. void pacifica_one_layer( CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff)
  96. {
  97. uint16_t ci = cistart;
  98. uint16_t waveangle = ioff;
  99. uint16_t wavescale_half = (wavescale / 2) + 20;
  100. for( uint16_t i = 0; i < NUM_LEDS; i++) {
  101. waveangle += 250;
  102. uint16_t s16 = sin16( waveangle ) + 32768;
  103. uint16_t cs = scale16( s16 , wavescale_half ) + wavescale_half;
  104. ci += cs;
  105. uint16_t sindex16 = sin16( ci) + 32768;
  106. uint8_t sindex8 = scale16( sindex16, 240);
  107. CRGB c = ColorFromPalette( p, sindex8, bri, LINEARBLEND);
  108. leds[i] += c;
  109. }
  110. }
  111. // Add extra 'white' to areas where the four layers of light have lined up brightly
  112. void pacifica_add_whitecaps()
  113. {
  114. uint8_t basethreshold = beatsin8( 9, 55, 65);
  115. uint8_t wave = beat8( 7 );
  116. for( uint16_t i = 0; i < NUM_LEDS; i++) {
  117. uint8_t threshold = scale8( sin8( wave), 20) + basethreshold;
  118. wave += 7;
  119. uint8_t l = leds[i].getAverageLight();
  120. if( l > threshold) {
  121. uint8_t overage = l - threshold;
  122. uint8_t overage2 = qadd8( overage, overage);
  123. leds[i] += CRGB( overage, overage2, qadd8( overage2, overage2));
  124. }
  125. }
  126. }
  127. // Deepen the blues and greens
  128. void pacifica_deepen_colors()
  129. {
  130. for( uint16_t i = 0; i < NUM_LEDS; i++) {
  131. leds[i].blue = scale8( leds[i].blue, 145);
  132. leds[i].green= scale8( leds[i].green, 200);
  133. leds[i] |= CRGB( 2, 5, 7);
  134. }
  135. }