
#define LED_COUNT              8
#define UP                     1
#define DOWN                   2
#define PWM_PRECISION          8
#define PWM_VALUE_MAX          1 << PWM_PRECISION
#define PIN_BUTTON             13
#define BUTTON_UP              1
#define BUTTON_BOUNCING        2
#define BUTTON_DOWN            3
#define BUTTON_HELD            4

const byte ledPins[] = {21, 47, 38, 39, 40, 41, 42, 2};  //define led pins
const byte chns[] = {0, 1, 2, 3, 4, 5, 6, 7};  //define the pwm channels
int pwmvalues[] = {1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7};
char velocities[] = {DOWN, DOWN, DOWN, DOWN, DOWN, DOWN, DOWN, DOWN};
int delayTimes = 100;  //flowing speed ,the smaller, the faster
unsigned long button_bounce_millis = 0;
char buttonState = BUTTON_UP;

void setup() {
  for (int i = 0; i < LED_COUNT; i++) {  //setup the pwm channels
    ledcAttachChannel(ledPins[i], 1000, PWM_PRECISION, chns[i]);
  }
  pinMode(PIN_BUTTON, INPUT);
}

void checkButtonPressed(void) {
  unsigned long curmillis = millis();
  if ( digitalRead(PIN_BUTTON) == LOW ) {
    if ( buttonState == BUTTON_UP ) {
      button_bounce_millis = millis();
      buttonState = BUTTON_BOUNCING;
      return;
    } else if ( buttonState == BUTTON_BOUNCING && curmillis - button_bounce_millis > 20 ) {
      if ( digitalRead(PIN_BUTTON) == LOW ) {
        buttonState = BUTTON_DOWN;
      }
    }
  } else if ( digitalRead(PIN_BUTTON) == HIGH ) {
    buttonState = BUTTON_UP;
  }
}

void loop() {
  checkButtonPressed();
  if ( buttonState == BUTTON_DOWN ) {
    for ( int i = 0; i < LED_COUNT ; i++ ) {
      if ( velocities[i] == UP) {
        velocities[i] = DOWN;
      } else {
        velocities[i] = UP;
      } 
    }
    buttonState = BUTTON_HELD;
  }

  for ( int i = 0; i < LED_COUNT ; i++ ) {
    if ( pwmvalues[i] == 0 ) {
      velocities[i] = UP;
      pwmvalues[i] = 1;
    } else if ( pwmvalues[i] == PWM_VALUE_MAX ) {
      velocities[i] = DOWN;
    }
    if ( velocities[i] == UP ) {
      pwmvalues[i] = pwmvalues[i] << 1;
    } else if ( velocities[i] == DOWN ) {
      pwmvalues[i] = pwmvalues[i] >> 1;
    }
    ledcWrite(ledPins[i], pwmvalues[i]);
  }
  delay(delayTimes);  
}
