// LED patterns with shift registers

#define dataPin  0 // DS
#define clockPin 1 // SHCP
#define latchPin 2 // STCP

#define regPins 1 * 8 + 4 // shift register output pins

bool registers[regPins];
bool state = false;

void setup() {
  randomSeed(analogRead(A0));
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  clearRegisters();
  writeRegisters();
}

void loop() {
  // randomize();
  // toggle();
  pendulum();
  // propeller();
}

//**************************************************
// display functions
//**************************************************

void randomize() {
  int i = random(regPins);
  setRegisterPin(i, HIGH);
  writeRegisters();
  delay(100);
  setRegisterPin(i, LOW);
  writeRegisters();
}

void toggle() {
  for (int i = 0; i < regPins; i++) {
    if (!(i % 2)) {
      setRegisterPin(i, state);
    } else {
      setRegisterPin(i, !state);
    }
    writeRegisters();
  }
  state = !state;
  delay(250);
}

void propeller() {
  for (int i = 0; i < regPins; i++) {
    setRegisterPin(i, !state);
    writeRegisters();
    delay(100);
    setRegisterPin(i, state);
    writeRegisters();
  }
}

void pendulum() {
  for (int j = 0; j < 2; j++) {
    for (int i = 0; i < regPins; i++) {
      if (j)
        setRegisterPin(i, !state);
      else
        setRegisterPin((regPins - 1) - i, !state);
      writeRegisters();
      delay(100);
      if (j)
        setRegisterPin(i, state);
      else
        setRegisterPin((regPins - 1) - i, state);
      writeRegisters();
    }
  }
}

//**************************************************
// utility functions
//**************************************************
void clearRegisters() {
  for (int i = 0; i < regPins; i++) {
    registers[i] = LOW;
  }
}

void setRegisterPin(int index, int value) { // set individual pins
  registers[index] = value;
}

void writeRegisters() {
  digitalWrite(latchPin, LOW);
  for (int i = 0; i < regPins; i++) {
    digitalWrite(clockPin, LOW);
    digitalWrite(dataPin, registers[i]);
    digitalWrite(clockPin, HIGH);

    // STANDARD METHOD
    // digitalWrite(latchPin, LOW);
    // shiftOut(dataPin, clockPin, LSBFIRST, pattern);
    // digitalWrite(latchPin, HIGH);
  }
  digitalWrite(latchPin, HIGH);
}

/************************************************************************************************
  ATTINY85                             +-- --+
             PCINT5/-RESET/ADC0/dW/PB5 |1 * 8| VCC
      PCINT3/XTAL1/CLKI/-OC1B/ADC3/PB3 |2   7| PB2/SCK/USCK/SCL/ADC1/T0/INT0/PCINT2
  PWM4/PCINT4/XTAL2/CLKO/OC1B/ADC2/PB4 |3   6| PB1/MISO/DO/AIN1/OC0B/OC1A/PCINT1/PWM1
                                   GND |4   5| PB0/MOSI/DI/SDA/AIN0/OC0A/-OC1A/AREF/PCINT0/PWM0
                                       +-----+
  // https://www.gadgetronicx.com/attiny85-timer-tutorial-generating-time-delay-interrupts/
************************************************************************************************/
ATTINY8520PU
74HC595
74HC595