#include "FastLED.h"

// Matrix size
#define HEIGHT 16
#define WIDTH 16
#define NUM_LEDS WIDTH * HEIGHT
#define MATRIX_TYPE 1
// LEDs pin
#define DATA_PIN 5
// LED brightness
#define BRIGHTNESS 255
// Define the array of leds
CRGB leds[NUM_LEDS];

//// ----------------------------- Sinusoid ------------------------------
//(c)Stefan Petrick https://gist.github.com/StefanPetrick/dc666c1b4851d5fb8139b73719b70149
//https://editor.soulmatelights.com/gallery/587
//upd by Stepko
bool loadingFlag = true;

uint8_t speed = 155;
uint8_t scale = 55;
uint8_t amplitude = 255;
int8_t type = 0; //0-3 original/>3 other versions

static float fmap(const float x, const float in_min, const float in_max, const float out_min, const float out_max) {
  return (out_max - out_min) * (x - in_min) / (in_max - in_min) + out_min;
}
const int8_t semiHeightMajor  =  HEIGHT / 2 + (HEIGHT % 2);
const int8_t semiWidthMajor = WIDTH / 2  + (WIDTH % 2);
float e_s3_speed;
float e_s3_size;
float _scale;
void Sinusoid() {
  if (loadingFlag) {
    e_s3_speed = 0.004 * speed + 0.015; // speed of the movement along the Lissajous curves
    e_s3_size = fmap(amplitude, 1, 255, 3, 9); // amplitude of the curves
    _scale = fmap(scale, 1, 255, 0.1, 3);
    loadingFlag = false;
  }
  float time_shift = millis();
  switch (type) {
    case 0://Sinusoid I
      for (uint8_t y = 0; y < HEIGHT; y++) {
        for (uint8_t x = 0; x < WIDTH; x++) {
          CRGB color;
          float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor;  // the 8 centers the middle on a 16x16
          float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
          float v = 127 * (1 + sinf ( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
          uint8_t data = v;
          leds[XY(x, y)].r = data;
          cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
          cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
          v = 127 * (1 + sinf( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
          data = v;
          leds[XY(x, y)].b = data;

        }
      }
      break;
    case 1://it's not sinusoid II
      for (uint8_t y = 0; y < HEIGHT; y++) {
        for (uint8_t x = 0; x < WIDTH; x++) {
          float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor;  // the 8 centers the middle on a 16x16
          float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
          float v = 127 * (sin(float(0.001 * time_shift * e_s3_speed)) + sinf ( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
          uint8_t data = v;
          leds[XY(x, y)].r = data;
          cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
          cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
          v = 127 * (sin(float(0.0025 * time_shift * e_s3_speed)) + sinf( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
          data = v;
          leds[XY(x, y)].g = data;
        }
      }  break;
    case 2://Sinusoid III
      for (uint8_t y = 0; y < HEIGHT; y++) {
        for (uint8_t x = 0; x < WIDTH; x++) {

          float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor;  // the 8 centers the middle on a 16x16
          float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
          float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )));
          uint8_t data = v;
          leds[XY(x, y)].r = data;

          cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
          cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
          v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )));
          data = v;
          leds[XY(x, y)].b = data;

          cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
          cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
          v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )));
          data = v;
          leds[XY(x, y)].g = data;

        }
      } break;
    case 3://Sinusoid IV
      for (uint8_t y = 0; y < HEIGHT; y++) {
        for (uint8_t x = 0; x < WIDTH; x++) {

          float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor;  // the 8 centers the middle on a 16x16
          float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
          float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )  + float(0.01 * time_shift * e_s3_speed)));
          uint8_t data = v;
          leds[XY(x, y)].r = data;

          cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
          cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
          v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )  + float(0.01 * time_shift * e_s3_speed)));
          data = v;
          leds[XY(x, y)].b = data;

          cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
          cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
          v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )  + float(0.01 * time_shift * e_s3_speed)));
          data = v;
          leds[XY(x, y)].g = data;

        }
      }

      break;
    case 4: //changed by stepko //anaglyph sinusoid
      for (uint8_t y = 0; y < HEIGHT; y++) {
        for (uint8_t x = 0; x < WIDTH; x++) {

          float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor;  // the 8 centers the middle on a 16x16
          float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
          float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
          uint8_t data = v;
          leds[XY(x, y)].r = data;

          v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy))  + float(0.01 * time_shift * e_s3_speed))));
          data = v;
          leds[XY(x, y)].b = data;

          v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy))  + float(0.01 * time_shift * e_s3_speed))));
          data = v;
          leds[XY(x, y)].g = data;

        }
      }
      break;
    case 5: //changed by stepko //colored sinusoid
      for (uint8_t y = 0; y < HEIGHT; y++) {
        for (uint8_t x = 0; x < WIDTH; x++) {

          float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor;  // the 8 centers the middle on a 16x16
          float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
          float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
          uint8_t data = v;
          leds[XY(x, y)].r = data;

          v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy))  + float(0.01 * time_shift * e_s3_speed))));
          data = v;
          leds[XY(x, y)].b = data;

          v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy))  + float(0.025 * time_shift * e_s3_speed))));
          data = v;
          leds[XY(x, y)].g = data;

        }
      }
      break;
    case 6: //changed by stepko //sinusoid in net
      for (uint8_t y = 0; y < HEIGHT; y++) {
        for (uint8_t x = 0; x < WIDTH; x++) {

          float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor;  // the 8 centers the middle on a 16x16
          float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
          float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
          uint8_t data = v;
          leds[XY(x, y)].g = data;

          v = 127 * (1 + sinf (_scale * x  * 10  + float(0.01 * time_shift * e_s3_speed)));
          data = v;
          leds[XY(x, y)].b = data;

          v = 127 * (1 + sinf (_scale * y  * 10  + float(0.011 * time_shift * e_s3_speed)));
          data = v;
          leds[XY(x, y)].r = data;

        }
      }
      break;
    case 7: //changed by stepko //spiral
      for (uint8_t y = 0; y < HEIGHT; y++) {
        for (uint8_t x = 0; x < WIDTH; x++) {
          float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor;  // the 8 centers the middle on a 16x16
          float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
          float v = 127 * (1 + sinf (3 * atan2(cy, cx)  + _scale *  hypot(cy, cx) + float(0.01 * time_shift * e_s3_speed)));
          uint8_t data = v;
          leds[XY(x, y)].r = data;

          cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
          cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
          v = 127 * (1 + sinf (3 * atan2(cy, cx)  + _scale *  hypot(cy, cx) + float(0.01 * time_shift * e_s3_speed)));
          data = v;
          leds[XY(x, y)].b = data;

          cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
          cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
          v = 127 * (1 + sinf (3 * atan2(cy, cx)  + _scale * hypot(cy, cx) + float(0.01 * time_shift * e_s3_speed)));
          data = v;
          leds[XY(x, y)].g = data;

        }
      }
      break;
    /*case 8: //changed by stepko //blobs
      for (uint8_t y = 0; y < HEIGHT; y++) {
        for (uint8_t x = 0; x < WIDTH; x++) {
          float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor;  // the 8 centers the middle on a 16x16
          float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
          float  v = 30 * (max(0, -hypot(cx, cy) + _scale * 2.5));
          uint8_t data = v;
          leds[XY(x, y)].r = data;

          cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
          cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
          v = 30 * (max(0, -hypot(cx, cy) + _scale * 2.5));
          data = v;
          leds[XY(x, y)].b = data;

          cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
          cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
          v = 30 * (max(0, -hypot(cx, cy) + _scale * 2.5));
          data = v;
          leds[XY(x, y)].g = data;

        }
      }
      break;*/
  }
}


void setup() {
  //Serial.begin(250000);
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  pinMode(2, INPUT_PULLUP);
}

void loop() {
  bool buttonPressed = digitalRead(2) == LOW;
  Sinusoid();
  if (buttonPressed) {
    if (type >= 8) {
      type = 0;
    } else {
      type += 1;
    }
    FastLED.clear();
    delay(100);
  } else {
    FastLED.show();
    FastLED.delay(1000 / 60);
  }
} //loop


uint16_t XY (uint8_t x, uint8_t y) {
  return (y * WIDTH + x);
}
FPS: 0
Power: 0.00W