#include <LiquidCrystal.h>
#define ARR_SIZE 16 // CHANGE this to any number of frames
#define LIGHTS 8
// Controls the game button inputs
const int btn1 = 7, btn2 = 8, btn3 = 9, btn4 = 10;
// Variable for reading the pushbutton status
int bs1 = 0, bs2 = 0, bs3 = 0, bs4 = 0;
// Pin connected to ST_CP of 74HC595
const int latchPin = 11;
// Pin connected to SH_CP of 74HC595
const int clockPin = 13;
// Pin connected to DS of 74HC595
const int dataPin = 12;
// Holders for information you're going to pass
byte data;
// Used to read either 1 or 0
bool ArrOne[ARR_SIZE][LIGHTS] = {false}; // animation
// Translated for the register as bytes
byte lightArrOne[ARR_SIZE] = {0xFF};
// Variables to affect the animation
int animSpeed = 50; // ms between each frame
int loopCount = 5; // amount of times it will run
// Controls LCD Values
const int rs = 15, en = 14, d4 = 3, d5 = 4, d6 = 5, d7 = 6;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup()
{
// Set each button up
pinMode(btn1, INPUT_PULLUP);
pinMode(btn2, INPUT_PULLUP);
pinMode(btn3, INPUT_PULLUP);
pinMode(btn4, INPUT_PULLUP);
// Set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Set register latch
pinMode(latchPin, OUTPUT);
PrintMenu();
}
void loop()
{
bs1 = digitalRead(btn1);
bs2 = digitalRead(btn2);
bs3 = digitalRead(btn3);
bs4 = digitalRead(btn4);
// Play the anim
if(bs1 == HIGH)
{
bs1 = LOW;// just used to prevent bad/double input
delay(150);
Play();
// Modify the anim
} else if(bs2 == HIGH)
{
bs2 = LOW;
delay(150);
Create(ArrOne);
// Change the speed of the anim
} else if(bs3 == HIGH)
{
bs3 = LOW;
delay(150);
SetSpeed();
// Change the number of times the anim will play
} else if(bs4 == HIGH)
{
bs4 = LOW;
delay(150);
SetLoop();
}
PrintMenu();
delay(150);
}
// Function to print info for the main menu
void PrintMenu()
{
ClearScreen();
lcd.print("1-Play 3-Speed");
lcd.setCursor(0, 1);
lcd.print("2-Create 4-Loops");
}
// Function to print info for creating a frame
void PrintCreate(bool Arr[][LIGHTS], int frame, int _bit)
{
ClearScreen();
lcd.print("Frame:");
lcd.print(frame+1);
if(frame < 9)
lcd.print(" ");
for(int j = 0; j < _bit; j++)
lcd.print(" ");
lcd.print("v");
lcd.setCursor(0, 1);
lcd.print(" ");
for(int j = 0; j < 8; j++)
lcd.print(Arr[frame][j]);
}
// Function to print info for setting the speed
void PrintSetSpeed()
{
ClearScreen();
lcd.print("Set Speed(ms)");
lcd.setCursor(0, 1);
lcd.print(animSpeed);
}
// Function to print info for changing the number of animation loops
void PrintSetLoop()
{
ClearScreen();
lcd.print("Set Loop Count");
lcd.setCursor(0, 1);
lcd.print(loopCount);
}
// Function to play the animation with the given parameters
void Play()
{
// The animation
for(int count = 0; count < loopCount; count++)
{
for(int i = 0; i < ARR_SIZE; ++i)
{
//load the light sequence you want from array
data = lightArrOne[i];
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, data);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
delay(animSpeed);
}
}
data = 0;
for(int i = 0; i < ARR_SIZE; ++i)
{
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, data);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
}
}
// Menu for creating a frame
void Create(bool Arr[][LIGHTS])
{
// Waits for the user's input for one of the buttons
for(int frame = 0; frame < ARR_SIZE; frame++)
{
bool leaving = false;
int b = 0;
while((!leaving) && (b < LIGHTS))
{
PrintCreate(Arr, frame, b);
// Ensure b is in bounds
if(b < 0 && frame > 0) {
b = LIGHTS-1;
frame--;
}
bs1 = digitalRead(btn1);
bs2 = digitalRead(btn2);
bs3 = digitalRead(btn3);
bs4 = digitalRead(btn4);
if(bs1 == HIGH)
{
delay(150);
Arr[frame][b] = true;
b++;
} else if(bs2 == HIGH)
{
delay(150);
Arr[frame][b] = false;
b++;
} else if(bs3 == HIGH)
{
delay(150);
b--;
} else if(bs4 == HIGH)
{
delay(150);
leaving = true;
}
delay(10);
}
PrintCreate(Arr, frame, b);
IntToHexToByte(Arr);
delay(500);
}
}
// Function to convert the array into a byte for the register to read
void IntToHexToByte(bool Arr[][LIGHTS])
{
for(int row = 0; row < ARR_SIZE; row++)
{
lightArrOne[row] = BoolArrayToByte(Arr, row);
}
}
// Helper function to convert binary to a byte
byte BoolArrayToByte(bool Arr[][LIGHTS], int row)
{
byte result = 0;
for(int i = 0; i < LIGHTS; i++)
{
if(Arr[row][i])
result = result | (1 << i);
}
return result;
}
// Menu to set the speed of the animation
void SetSpeed()
{
bool leaving = false;
while(!leaving)
{
PrintSetSpeed();
bs1 = digitalRead(btn1);
bs2 = digitalRead(btn2);
bs3 = digitalRead(btn3);
bs4 = digitalRead(btn4);
// Increase the speed
if(bs1 == HIGH)
{
delay(10);
animSpeed++;
}
// Decrease the speed
if(bs2 == HIGH)
{
delay(10);
if(animSpeed > 1)
animSpeed--;
}
// Increase the speed
if(bs4 == HIGH)
{
delay(150);
leaving = true;
}
delay(30);
}
}
// Function to change the number of times the anim loops
void SetLoop()
{
bool leaving = false;
while(!leaving)
{
PrintSetLoop();
bs1 = digitalRead(btn1);
bs2 = digitalRead(btn2);
bs3 = digitalRead(btn3);
bs4 = digitalRead(btn4);
if(bs1 == HIGH)
{
delay(10);
loopCount++;
}
if(bs2 == HIGH)
{
delay(10);
if(animSpeed > 1)
loopCount--;
}
if(bs4 == HIGH)
{
delay(150);
leaving = true;
}
delay(30);
}
}
// Function to actually shift the bits in the register
void shiftOut(int myDataPin, int myClockPin, byte myDataOut)
{
// This shifts 8 bits out MSB first,
// on the rising edge of the clock,
// clock idles on low
//internal function setup
int i = 0;
int pinState;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);
//clear everything out just in case to
//prepare shift register for bit shifting
digitalWrite(myDataPin, 0);
digitalWrite(myClockPin, 0);
// Each bit in the byte myDataOut
for (i = 7; i >= 0; i--) {
digitalWrite(myClockPin, 0);
if ( myDataOut & (1 << i) ) {
pinState = 1;
}
else {
pinState = 0;
}
//Sets the pin to HIGH or LOW depending on pinState
digitalWrite(myDataPin, pinState);
//register shifts bits on upstroke of clock pin
digitalWrite(myClockPin, 1);
//zero the data pin after shift
digitalWrite(myDataPin, 0);
}
//stop shifting
digitalWrite(myClockPin, 0);
}
// Function to clear the LCD by printing spaces
void ClearScreen()
{
//Iterates through each row and prints a blank
lcd.setCursor(0, 0);
for(int col = 0; col < 16; col++)
lcd.print(" ");
lcd.setCursor(0, 1);
for(int col = 0; col < 16; col++)
lcd.print(" ");
lcd.setCursor(0, 0);
}
Comments
Please log in or sign up to comment.