// originally from:
// https://github.com/sutaburosu/scintillating_heatshrink/

#include <Arduino.h>
#include <FastLED.h>

/*
если хотите управлять питанием лентой транзистором  раскоментируйте #define PIN_NPN и укажите пин на каторый он подключен
если хотите плавную заливку заливку светодиодов раскоментируйте #define LED_START
*/
//#define PIN_NPN 3
#define LED_START true

#define PIN 2
#define NUM_LEDS 64

CRGB leds[NUM_LEDS];
byte counter;
byte led_brig = 100; //яркость светодиодов при старте
byte led_mode; //режим работы
int led_timer; //для таймера
byte led_sped = 5; //скорость эффекта

void setup() {
    Serial.begin(9600);
    Serial.println("");
    #if defined PIN_NPN
        pinMode(PIN_NPN, OUTPUT);
        digitalWrite(PIN_NPN, true);
    #endif
    FastLED.addLeds<WS2812, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    #if defined LED_START
        for(byte i; i <= led_brig; i++) {
            FastLED.setBrightness(i); //увеличиваем яркость на 1 до значения переменой led_brig
            effect_rainbow(); //запускаем эффект радуги
            delay(50); //задержка
        }
    #else
        FastLED.setBrightness(led_brig); //устанавливаем яркость
    #endif
    led_mode = 1; //установливаем режим 1 радуга
}
void loop() {
    if(Serial.available() > 2) { //если в буфере порта больше 2 байт начинаем парсить
        switch(Serial.read()) {
            case 77: //если первый байт равен символу M
            case 109: { //или m то меняем мод. То есть если отправить M0 светодиоды погаснут M1 включится эффект радугу M2 рандомный эффект M3 сплошной цвет и тд если допишишь
                byte i = Serial.parseInt(); //читаем значения после команды m
                if(i < 4) { //если значения меньше доступных режимов
                    led_mode = i; //присваиваем его как мод
                    if(led_mode == 0) { //если пришла команда отключить отключаем
                        #if defined PIN_NPN
                            digitalWrite(PIN_NPN, false); //просто дергаем транзистором
                        #else
                            FastLED.clear();//очищает ленту, буквально обнуляет все цвета в массиве, задаёт “чёрный” цвет.
                            FastLED.setBrightness(0); // уберем яркость
                            FastLED.show();//обновляем
                        #endif
                    }
                    else { //включпем
                        #if defined PIN_NPN
                            digitalWrite(PIN_NPN, true); //просто дергаем транзистором
                        #else
                            FastLED.setBrightness(led_brig); // ставим яркость
                        #endif
                        counter = random(0, 255); //задаем рандомный цвет
                        effect_fadeall();
                    }
                    Serial.print("mode = ");
                    Serial.println(led_mode);
                }
                break; //выодим
            }
            case 67: //если первый байт равен символу C
            case 99: { //или c то меняем цвет от 0 до 255 пригодится для сплошной заливки
                counter = Serial.parseInt(); //читаем значения после команды c
                effect_fadeall();
                Serial.print("color = ");
                Serial.println(counter);
                break; //выодим
            }
            case 83: //если первый байт равен символу S
            case 115: { //или s то меняем скорость эффекта от 0 до 255
                led_sped = Serial.parseInt(); //читаем значения после команды s
                Serial.print("sped = ");
                Serial.println(led_sped);
                break; //выходим
            }
            case 66: //если первый байт равен символу B
            case 98: { //или b то меняем яркость от 0 до 255
                led_brig = Serial.parseInt(); //читаем значения после команды b
                if(led_mode) {
                    FastLED.setBrightness(led_brig);
                    FastLED.show();
                }
                Serial.print("bring = ");
                Serial.println(led_brig);
                break; //выходим
            }
            
            
        }
    }
    int m = int(millis());
    if(m-led_timer > led_sped) {
        led_timer = m;
        switch(led_mode) {
            case 1: effect_rainbow();  break;
            case 2: effect_random();  break;
            //третий не надо как достаточно его раз залить будешь добавлять тут с четвертого начнешь и в веру проверку надо будет изменить if(i < 4)
        }
    }
}

void  effect_random() {
    leds[random(0, NUM_LEDS)].setHue(random(0, 255)); //рандомный светодиод и цвет
    FastLED.show();
}

void  effect_rainbow() {
    for(int i = 0; i < NUM_LEDS; i++ )  leds[i].setHSV(0,0,255);
    counter++;
    FastLED.show();
}

void effect_fadeall()  {
  for (int i = 0; i < NUM_LEDS; i++) leds[i].setHue(counter);
  FastLED.show();
}