#include <TinyDebug.h>

#define latchPin PB2
#define clockPin PB1
#define dataPin PB0

uint8_t numOfRegisters = 2;

uint8_t registerState[] = {0, 0};

uint8_t effectId = 0;
uint8_t prevEffect = 0;
uint8_t effectRepeat = 0;
uint8_t effectSpeed = 30;

void setup() {
	Debug.begin();
	pinMode(latchPin, OUTPUT);
	pinMode(clockPin, OUTPUT);
	pinMode(dataPin, OUTPUT);
}

void loop() {
	do {
		effectId = random(6);
	} while (effectId == prevEffect);
	prevEffect = effectId;

	switch (effectId)
	{
	case 0:
		effectRepeat = random(1, 2);
		break;
	case 1:
		effectRepeat = random(1, 2);
		break;
	case 3:
		effectRepeat = random(1, 5);
		break;
	case 4:
		effectRepeat = random(1, 2);
		break;
	case 5:
		effectRepeat = random(1, 2);
		break;
	}

	for (int i = 0; i < effectRepeat; i++) {
		effectSpeed = random(10, 90);

		switch (effectId)
		{
		case 0:
			effectA(effectSpeed);
			break;
		case 1:
			effectB(effectSpeed);
			break;
		case 3:
			effectC(effectSpeed);
			break;
		case 4:
			effectD(effectSpeed);
			break;
		case 6:
			effectE(effectSpeed);
			break;
		}
	}
}

void effectA(int speed){
	for (int i = 0; i < 16; i++){
		for (int k = i; k < 16; k++){
			regWrite(k, HIGH);
			delay(speed);
			regWrite(k, LOW);
		}

		regWrite(i, HIGH);
	}
}

void effectB(int speed){
	for (int i = 15; i >= 0; i--){
		for (int k = 0; k < i; k++){
			regWrite(k, HIGH);
			delay(speed);
			regWrite(k, LOW);
		}

		regWrite(i, HIGH);
	}
}

void effectC(int speed){
	int prevI = 0;
	for (int i = 0; i < 16; i++){
		regWrite(prevI, LOW);
		regWrite(i, HIGH);
		prevI = i;

		delay(speed);
	}

	for (int i = 15; i >= 0; i--){
		regWrite(prevI, LOW);
		regWrite(i, HIGH);
		prevI = i;

		delay(speed);
	}
}

void effectD(int speed){
	for (int i = 0; i < 8; i++){
		for (int k = i; k < 8; k++)
		{
			regWrite(k, HIGH);
			regWrite(15 - k, HIGH);
			delay(speed);
			regWrite(k, LOW);
			regWrite(15 - k, LOW);
		}

		regWrite(i, HIGH);
		regWrite(15 - i, HIGH);
	}
}

void effectE(int speed){
	for (int i = 7; i >= 0; i--){
		for (int k = 0; k <= i; k++)
		{
			regWrite(k, HIGH);
			regWrite(15 - k, HIGH);
			delay(speed);
			regWrite(k, LOW);
			regWrite(15 - k, LOW);
		}

		regWrite(i, HIGH);
		regWrite(15 - i, HIGH);
	}
}

void regWrite(int pin, bool state){
	// Determines if register is 0 or 1
	int reg = pin / 8; // (0-7 / 8 = 0) , (8-15 / 8 = 1)
	Debug.print("reg:"); Debug.print(reg);
	// Determines pin for actual register
	int actualPin = pin - (8 * reg); // (0-15 - (8 * 0)is 0,  or (8 * 1)is 8, = 0 to 15 or -8 to 7
	Debug.print(", pin:"); Debug.print(pin);
	Debug.print(", actualPin:"); Debug.println(actualPin);

	//Begin session
	digitalWrite(latchPin, LOW);

	for (int i = 0; i < numOfRegisters; i++){
		//Get actual states for register
		// *states is a pointer to the memory address of registerState[0] and registerState[1]
		byte* states = &registerState[i];
    

		//Update state
		if (i == reg){
			bitWrite(*states, actualPin, state); 	// first time through loop *states is = to registerState[0]
		}																				// next time through loop *states is = to registerState[1]

		//Write
		shiftOut(dataPin, clockPin, LSBFIRST, *states); // same here registerState[0] then registerState[1]
    
	}

	//End session
	digitalWrite(latchPin, HIGH);
}
ATTINY8520PU
74HC595
74HC595