Game Designer: Unknown
Game Designer: Unknown
FrankenTimer
King of the Hill Arduino Timer V4/V5


New Timer!
It's time to incorporate what I've learned during the 2023 season of gameplay. This new iteration is called the FrankenTimer.
-
LiPo's are annoying and so I'm moving to a USB power bank. We ended up killing a couple of LiPo's so I'm just going to move away from them.
-
4 Pin LEDs add unnecessary complexity and the 12V LEDs I was using aren't much brighter than the 5V 3 Pin LEDs I'm using now.
-
Wiring this thing creates a rats nest, it's time to design a 3D printed housing.
-
Rotary encoders/ buttons are awesome and make the admin experience so much better.
-
The audio sounds are a nice to have and are not necessary for those just starting off. It really should be an upgrade rather than part of the base unit.
​
I want to give a special thanks to the Nerfer DonutCat for showing me how the 3 pin LEDs and rotary encoder/button make things just that much better. I also want to thank Boomstick Mods for letting me test my ideas at our Maryland Nerf Herder games.
For those who built the old V3 timer, the updated the code works with either hardware version. Eventually this might not be the case but I will try and maintain cross compatibility as long as possible. However, I recommend upgrading to the rotary encoder as it is really nice for navigation purposes.
​
Introduction
This is a guide for creating a purpose built timer for playing nerf. This was heavily inspired by Aldoss's YouTube videos with John's timer at Rochester Parkour.
I designed, built and programmed this from scratch. Since I figured it out, I decided to share it with everyone else. I'm currently on version 4. To see V3 click here.
Below are the essential building blocks for building an Arduino based timer for king of the hill and other game modes. The programming is already complete, so you just need to buy the parts and assemble it. It will require soldering and other basic modding skills. While it may appear overwhelming, I break it down into manageable steps. This is a guide on how to do the electronics and can be paired with my assembly guide for my 3D printable housing.
The timer has all sorts of bells and whistles so it is not the cheapest. Hopefully in the future I can make a version that is less expensive.

The write up, wiring diagram, and Arduino code of this website is licensed under the Creative Commons - Attribution - Noncommercial - ShareAlike license.
Table of Contents
Parts List:
Amazon Affiliate Links Included
Total Cost: $100 - $300. Many items are only sold in packs which drive the cost up.
Base Unit
Uncommon Items
$23 - Arduino Mega with Cord (1 each)
$23 - LEDs (16 ft, only need about 4 ft)
$11 - LCD Screen (2 pack, only need 1)
$6 - 220 ohm resistors (100 pack, only need 5)
$9 - Dupont 30 cm Wires (Recommended)
$10 - Red Button (1 each)
$10 - Blue Button (1 each)
$20 - USB Power Bank (2 pack, only need 1)
$15 - USB Connectors (4 pack, only need 2)
$11 - Rotary Encoder (5 pack, only need 1)
$7 - Rocker Switch (5 pack, only need 1)
​
Common Items
$8 - Heat Shrink Tubing (Variety Pack)
$13 - 18 awg Silicone Wire (Black and Red)
$8 - Electrical Wire Twist Caps (Variety pack, only need 4)
​
Upgrade 1 (wiring diagram complete)
$10 - MP3 Controller (2 pack, only need 1)
$8 - Micro SD card
$11 - Aux 3.5mm Cable (6 pack, only need 1)
​
​
Upgrade 2 (wiring diagram complete)
Remote Starter: I finally think I figured out how to get the wireless communication working. It's pretty basic right now but I figured I would share earlier rather than later. Click Here for more details.
​
Upgrade 3 (wiring diagram still pending)
Large number Display (Recommend for Indoor use ONLY)
$18 ea - 7 segment display X 2
​
Alternate Purchase List:
I want to express a big thanks to PiggyJJ for helping put together a list of Taobao links for the various electronic components. If you are willing to brave Taobao and don't mind waiting a little bit longer this is a great way to save some money. You can download a excel file below with all the links and some of the notes that I made. PiggyJJ was an early adopter of my timer so if you want to see some game play go check out his YouTube channel
Tools List:
-
Computer
-
Cable to connect Arduino to computer (Should come with the Arduino)
-
Soldering Iron and solder
-
Wire strippers
-
Snips
-
Multimeter
-
3D Printer (Optional)
-
Wire Crimper (Optional)
Step 1: Create a Layout
I highly recommend figuring out the layout of the electronics prior to doing anything else. If you are using your own housing I suggest going back and looking at my layout advice from V3. My 3D printable housing will solve a lot of the issues of figuring out a layout.
​
For the Arduino, buttons, LCD screen, rotary encoder, LED signal and MP3 player I used the pre-made DuPont wires since they do not draw much current. For the LEDs and main power I use 18 awg wire since they draw more current.
Step 2: The Buttons


Warning! I've found the button LED (ie Pin 2 and 4) are not always consistent. Try pulling out the LED and flipping it. For the buttons I cut the DuPont Wires and solder on a short section of the male side to the button to allow me to easily disconnect it from the main body. Start by soldering wires to the button switch terminals. Solder a 220 ohms resistor to the LED terminal then solder the wire to the other end of the resistor. Solder the two negative power terminals together and don’t forget to add the heat shrink tubing.
Don't forget to leave enough slack in the wires for assembly and disassemble.
Step 3: The LCD Screen




The LCD screen has DuPont connectors which makes it easy to attach and detach wires.
​
Warning! Don't throw away the LCD screen paperwork, you might need it. I've found not all LCD screens use the same coding, if your LCD screen is not working then you might need to change one line of the code in the program. It's easy to change the code and I will talk about it more in the programming section of the write up. Also adjust the brightness of the screen with a screwdriver by turning the resistor (blue box).
Step 4: The LEDs


Time for the LEDs, which are so much simpler than V3. Soldering to the LED strip is a real pain. You can buy quick solderless connectors, to avoid the hassle if you want but is unnecessary unless you are building a bunch.
The signal wire (ie Din) is a cut DuPont wire with the male end still attached. The power and negative power gauge wire depends on the number of LEDs. More LEDs draws more current and requires thicker wire.
I use roughly 60 LEDs, each LED requires ~ 60 mA at max load. This means I am pulling approximately 3,600 mA’s through the wire. 18 awg wire ais rated for 14,000 mA’s so a thinner wire could be used if you desire. You could easily replace the 18 awg wire with 20 awg wire. If you add more than 60 LEDs make sure you have the correct gauge wire and note that you might be limited by the number of amps the USB bank can supply.
Solder two 220 ohm resistors to the wire with the male DuPont connector. Then solder that to the center terminal (I like to have a bit of wire between the resistors and the terminal). I then solder a red 18 awg wire to the +5V terminal and a black 18 awg wire to the GND terminal.
The solder connection to the LED strip is not very strong so add some glue and put heat shrink tubing over the end of the strip. I also zip tie the wires together at this location for added strength.
Step 5: The MP3 Player




Similar to the LCD screen the mp3 player has DuPont connectors, so you can just use those.
​
For the mp3 player make sure you have access to remove and install the micro SD card and run the aux cable to your speaker.
Step 6: Rotary Encoder/ Button



The rotary encoder/button has 3 terminals on one side (encoder) and 2 terminals on the other side (button). You can just solder Dupont wires to each of these. Note there is also a metal prong on the left and right side as shown in the picture above which are not used and I do not believe have any kind of electrical connection.
Step 7: The Power Switch/ Connector




Warning! make sure the battery is disconnected when doing the wiring.
Solder two red (positive) 18 awg wires to each of the terminals on the on/off (power) switch. Install the on/off switch in the housing prior to connecting the wires to the other locations. Two wires from one terminal go to the USB connectors (which can just be screwed on), the two wires from the other terminal go to the twist cap junctions TC-2 and TC-3.
Connect the the black (negative) 18 awg wires from the USB connectors to twist cap TC-1. Connect a 18 awg wire between TC-1 and TC-4. Next connect the brown/black (GND) wire from the buttons, LCD, rotary encoder, LED to TC-1. Connect the Arduino and mp3 GND wires to TC-4. I run all of the DuPont wires to the twist cap before I cut them so they are nice and neat.
Finally, connect the LED and LCD 5V wires to TC-2 and the Arduino and mp3 5V (VCC) wires to twist cap TC-3. The reason for the extra twist caps is to make assembly easier and to possibly allow for future hardware upgrades.
Step 8: The Micro SD
Warning! If you select all the files and drag and drop them onto the MicroSD card the timer won't be able to read them properly. The order you load the files onto the card matters.
​
Change Log:
2024-06-04 Added "Gained the Lead" sound bits 036 & 037.
​
First make sure that the mp3 files are properly named (i.e. 001, 002, etc). Second, drag and drop each file individually in ascending order onto the card. For example, drop file 001 first, 002 second, 003 third and so forth. It's a bit of a pain but it doesn't take that long.
Step 9: The Arduino Mega
You might ask why I used an Arduino Mega instead of an Uno or Nano, it's because I wanted the option to upgrade the timer with additional features. Also the difference in price between the Mega and Uno isn't significant. Nano's have enough connections for a basic timer but the code is inefficient so it requires the larger operating memory of a Mega.
Attaching the wires to the Arduino is where the DuPont wires come in useful. My connectors did came loose sometimes which is a downside but a little glue or tape could fix that. I'm planning on hot gluing mine in.
Connecting Wires To The Arduino/ Wiring Schematic:
Here is my attempt at a wiring diagram. The entire diagram may be a little intimidating but the above steps break it down into simple steps.
You'll notice each step has a simple wiring diagram showing which pin or twist cap (TC) the wire connects too. The full wiring diagram is to help understand the overall big picture.
Arduino Code:
Change Log:
2024-11-19 Added HOTPOT as a preprogrammed game mode.
​
2024-10-21 Added BTA KoTH as a preprogrammed game mode. Disabled 7 segment display due to library issue.
2024-09-28 Added ability to pause the Time Keeper by holding down any of the buttons for a quarter second. It will say paused and flash the LEDs red and blue. Hold down any of the buttons again to resume the timer. The LEDs will turnback to green once the timer resumes.
2024-06-04 Added "Gained the Lead" sound effects. Requires sound bits 036 & 037 be added to the SD card. See SD card section for new sounds.
2024-05-15 Fixed Start Delay and Audio Start timing. Now has a min start delay of 7 seconds when games have a set game length or are using the audio start countdown.
2024-03-18 Fixed Start Delay
Updated code to the new admin interface which uses the rotary encoder. I am by no means a programmer so forgive my ignorance/ poor coding etiquette. The code is not the prettiest or efficient but it does function.
I don't know how program libraries work or to check the correct ones are downloaded. However, Arduino Editor which is an online website for programing and uploading Arduino code already has the libraries pre installed to make the code run properly. You can sign up for a free account at https://create.arduino.cc/editor
In your account create a new sketch and copy/paste the code below into the window. Alternatively, download the .ino file with the button above then import it into your account.
Warning! The LEDs are tied to the Arduino so make sure you are plugged into the USB bank whenever the LEDs will be on other wise you could fry the Arduino. The Arduino start up code will not turn on the LEDs until you advance in the menu.
Connect the Arduino to the computer. In the drop down window select the Arduino that you plugged in. Then click upload. You may need to install some drivers to make the software work.
Assuming you've wired everything correctly then the LCD, mp3, rotary encoder/button and red/blue buttons should start working. The LEDs will turn on once you advance in the menu, make sure the timer is plugged into the USB power bank before the LEDs turn on.
​
LCD Screen Issue:
As mentioned, LCD screens don't always work using the same code (even when I use the same link on Amazon). It is because of the I2C address. Hopefully the LCD screen you order has paper work indicating which address to use but if not try these:
​
LiquidCrystal_I2C lcd(0x27, 16, 2);
or
LiquidCrystal_I2C lcd(0x3f, 16, 2);
​
Both lines of code can't be active. If your LCD screen is not working and you are certain that it is wired correctly then try changing the code. Deactivate one address and activate the other one. Locate the line in the code in the Arduino Editor by hitting ctrl + f and then searching LiquidCrystal.
Deactivate a line by adding // at the start of the line. Deactivated lines are grayed out. Conversely, activate a line by removing the //. If the LCD screen is still not working then you might want to check the brightness by rotating the screw in the blue box on the back.
//Arduino Code Posted Date 2024-02-26
/*
Please excuse my lack of programming etiquette, I'm not actually a programmer but I do what I can.
​
Currently...
//Posted Date 2024-02-26
/*
Please excuse my lack of programming ediquette, I'm not actually a programmer
but I do what I can.
Currently I have not gone in and cleaned up the code. There may be many instances
where comments are not quite accurate as I do a lot of copy and pasting. That
being said, the code does work.
*/
// Global Variables that change between Arduino Mega and Nano
//---------------------------------------------------------------------------------
//Arduino Mega
// Define pins for LED Strip
//Old V3 LED pins
#define REDPIN 45
#define GREENPIN 47
#define BLUEPIN 49
//New V4 LED pin
#define LED_PIN 6
#define LED_COUNT 42
//LCD Screen Pins
//SDA on UNO & Nano is A4. SDA on MEGA it is 20
//SCL on UNO & Nano is A5. SCL on MEGA it is 21
//Radio Reciever/Transmitter Code
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
int gogogo = 0;
RF24 radio(48, 46); // CE, CSN
//const byte addresses[][6] = {"00001", "00002"};
const byte address[6] = "T0001";
// Button Pins
int ledPinRed = 4; // Red Buttton LED Pin
int ledPinBlue = 2; // Blue Button LED Pin
int buttonRedpin = 5; // Red Button
int buttonBluepin = 3; // Blue Button
// MP3 Player
#define ARDUINO_RX 8 //should connect to RX of the Serial MP3 Player module
#define ARDUINO_TX 9 //connect to TX of the module
/*
//Arduino Nano - Code is too inefficient and takes up too much memory
// Define pins for LED Strip
#define REDPIN 2
#define GREENPIN 3
#define BLUEPIN 4
//LCD Screen Pins
//SDA on UNO & Nano is A4. SDA on MEGA it is 20
//SCL on UNO & Nano is A5. SCL on MEGA it is 21
//Radio Reciever/Transmitter Code
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
int gogogo = 0;
RF24 radio(7, 8); // CE, CSN
const byte address[6] = "T0001";
// Button Pins
int ledPinRed = A1; // Red Buttton LED Pin
int ledPinBlue = A2; // Blue Button LED Pin
int buttonRedpin = 9; // Red Button
int buttonBluepin = 10; // Blue Button
// MP3 Player
#define ARDUINO_RX 6 //should connect to RX of the Serial MP3 Player module
#define ARDUINO_TX 5 //connect to TX of the module
*/
//-------------------------------------------------------------------------------------
// End Global Variables that change between Arduino Mega and Nano
//LCD Screen
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27 or 0x3f, 16 column and 2 rows
//LiquidCrystal_I2C lcd(0x3f, 16, 2); // I2C address 0x27 or 0x3f, 16 column and 2 rows
//SDA on UNO is A4 on MEGA it is 20
//SLC on UNO is A5 on MEGA it is 21
String inputLCDText;
int delayLCD = 2500;
//Global Attrition
int redLifeCount;
int blueLifeCount;
int startLifeCount;
int attritionLifeIndex;
int attritionLifeSound;
int attritionLifeSoundModifier;
int gameAttritionArray[] = {1, 6, 11, 16};
//General Paramemters
String buttonMode;
String checkReset;
int teamHold;
int holdHillContested;
String teamInControl;
//used to help code when it is in standby
static int BlueFirst = 0;
static int RedFirst = 0;
struct gameParameters{
//These are variables for game setup
String buttonPush;
String timeX;
String timeLimit;
String timePause;
String timeReset;
String timeDirection;
String teamRunDown;
};
gameParameters selectOutput; //database for storing game setup parameters
struct tClock{
//These are variables for tracking the time
int m;
int k;
int j;
int i;
int mBlue;
int kBlue;
int jBlue;
int iBlue;
int mRed;
int kRed;
int jRed;
int iRed;
//Remove
//int mPause;
//int kPause;
//int jPause;
//int iPause;
int mHold;
int kHold;
int jHold;
int iHold;
int mLimit;
int kLimit;
int jLimit;
int iLimit;
String loopExit;
String Victory;
String teamRunDown;
};
//databases for storing time
tClock teamTime;
tClock timeOutput;
// Record time
struct Scorekeeper{
int timerName;
int blueTime;
int redTime;
int teamInControl;
};
Scorekeeper Score; // Contains data
//Remove
//byte leds = 0;
// Code for Millis From https://forum.arduino.cc/t/using-millis-for-timing-a-beginners-guide/483573
// this is used to track actual time kept by the Arduino
unsigned long startMillis; //some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 10000; //the value is a number of milliseconds
unsigned long startSecondMillis; //some global variables available anywhere in the program
unsigned long currentSecondMillis;
const unsigned long periodSecond = 1000; //the value is a number of milliseconds
unsigned long gameStartMillis;
unsigned long gameCheckMillis;
unsigned long gameCheckMillisCheck;
unsigned long gameLengthMillis;
unsigned long gameCheckMillis2;
unsigned long gameStartMillis2;
unsigned long xStartMillis;
unsigned long xCheckMillis;
unsigned long xLengthMillis;
// variables for audio count downs and reseting the timer
unsigned long gameRestart = 5000;//amount of milli seconds the two buttons need to be held down to reset the timer
unsigned long gameClockArray[] = {2, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 31000, 61000}; //used in the audio counting
unsigned long gameClockCheck;
int gameClockIndex = 12; // equals the size of array remember the first spot in an array is 0
int gameClockSound = 27; // tells audio count down what mp3 file to start counting from
String gameTimeOver;
String time2Reset;
String playGameStart;
String playGameEnd;
String alarmCheck;
//---------------------------Begin LED Strip Golbal code --------------------------------------------
//Code for 7 segment displays adapted from code written by Limor Fried/Ladyada from Adafruit Industries.
#include <Wire.h> // Enable this line if using Arduino Uno, Mega, etc.
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
Adafruit_7segment matrix = Adafruit_7segment();
// 3 Pin LED strip
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Declare NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
//-----------------------End of LED Strip global code -----------------------------
// --------------------- Begin Global Code for MP3 player ----------------------
#include <SoftwareSerial.h>
SoftwareSerial mp3(ARDUINO_TX, ARDUINO_RX);
static int8_t Send_buf[8] = {0}; // Buffer for Send commands. // BETTER LOCALLY
static uint8_t ansbuf[10] = {0}; // Buffer for the answers. // BETTER LOCALLY
String mp3Answer; // Answer from the MP3.
String sanswer(void);
String sbyte2hex(uint8_t b);
/************ Command byte **************************/
#define CMD_NEXT_SONG 0X01 // Play next song.
#define CMD_PREV_SONG 0X02 // Play previous song.
#define CMD_PLAY_W_INDEX 0X03
#define CMD_VOLUME_UP 0X04
#define CMD_VOLUME_DOWN 0X05
#define CMD_SET_VOLUME 0X06
#define CMD_SNG_CYCL_PLAY 0X08 // Single Cycle Play.
#define CMD_SEL_DEV 0X09
#define CMD_SLEEP_MODE 0X0A
#define CMD_WAKE_UP 0X0B
#define CMD_RESET 0X0C
#define CMD_PLAY 0X0D
#define CMD_PAUSE 0X0E
#define CMD_PLAY_FOLDER_FILE 0X0F
#define CMD_STOP_PLAY 0X16 // Stop playing continuously.
#define CMD_FOLDER_CYCLE 0X17
#define CMD_SHUFFLE_PLAY 0x18 //
#define CMD_SET_SNGL_CYCL 0X19 // Set single cycle.
#define CMD_SET_DAC 0X1A
#define DAC_ON 0X00
#define DAC_OFF 0X01
#define CMD_PLAY_W_VOL 0X22
#define CMD_PLAYING_N 0x4C
#define CMD_QUERY_STATUS 0x42
#define CMD_QUERY_VOLUME 0x43
#define CMD_QUERY_FLDR_TRACKS 0x4e
#define CMD_QUERY_TOT_TRACKS 0x48
#define CMD_QUERY_FLDR_COUNT 0x4f
/************ Opitons **************************/
#define DEV_TF 0X02
/*********************************************************************/
//Remove old Buzzer Code
/*
int numero;
byte estado;
byte buzzer = 2;
byte pin = 0;
byte SortNumber = 0;
bool button = 0;
*/
// ------------------------ End of MP3 ---------------------------------
//-------------------------------- Important -------------------------------------
//The order in which you load the sound tracks onto the micro SD card matters
// You should drag each sound track individually onto the micro SD card the order should match the numbering
//------------------------- Micro SD tracks ---------------------------
int kingofthehill = 001;
int gameover = 002;
int hillcontested = 3;
int hillcontrolled = 4;
int hilloccupied = 5;
int oneminutetowin = 6;
int blueteamminutetowin = 7;
int blueteam30secondstowin = 8;
int redteamminutetowin = 9;
int redteam30secondstowin = 10;
int redteamhillcontrolled = 11;
int blueteamhillcontrolled = 12;
int redteamwin = 13;
int blueteamwin = 14;
int stargatealarm = 15;
// 16 - 27 numbers for audio count down
int roundbegins = 28;
int overTimeSound = 29;
//Attrition
int noLivesSound = 30;
int attritionsound = 34;
//----------------------- End of Sound Tracks
//Variables for controlling direction of counting
int timeCheck_1Up = -9;
int timeCheck_2Up = -5;
int timeReset_1Up = 0;
int timeReset_2Up = 0;
int directionUp = -1;
int timeCheck_1Down = 0;
int timeCheck_2Down = 0;
int timeReset_1Down = 9;
int timeReset_2Down = 5;
int directionDown = 1;
int timeCheck_1;
int timeCheck_2;
int timeReset_1;
int timeReset_2;
int directionInput;
String Skip;
String runDownTeamColor;
String overTime;
String overTimeStart;
String variableX;
String checkX;
String gameSelectedMain;
//-------------Global Rotary Encoder --------------------------------
// Define rotary encoder pins
#define ENC_A 19
#define ENC_B 18
unsigned long _lastIncReadTime = micros();
unsigned long _lastDecReadTime = micros();
int _pauseLength = 25000;
int _fastIncrement = 10;
volatile int RotaryPosition = 0;
const int gameModeSelectionSize= 9;
String gameModeSelection[gameModeSelectionSize]= {"Custom", "Time Keeper", "KoTH", "Rogue One","Attrition","Death Clicks", "Domination","Hold The Hill", "Time Reset"};
// {name, buttonPush, timeX, timeLimit, timePause, timeReset, timeDirection}
String gameParametersArray[9][7]= { {"Custom","-","-","-","-","-", "-"},
{"Time Keeper","Tap","No","Yes","No","No", "Up"},
{"KoTH","Tap","X","No","No","No", "Down"},
{"Rogue One","Pause","X","Yes","Yes","No", "Down"},
{"Attrition","Pause","No","No","Yes","No", "Down"},
{"Death Clicks","Pause","No","No","Yes","No", "Up"},
{"Domination","Tap","X","Yes","No","No", "Up"},
{"Hold The Hill","Continuous","No","Yes","No","No", "Up"},
{"Time Reset","Pause","X","Yes","No","Yes", "Down"}
};
const int YesNoArraySize= 2;
String YesNoArray[YesNoArraySize]= {"Yes", "No"};
const int teamColorArraySize= 2;
String teamColorArray[teamColorArraySize]= {"Red", "Blue"};
const int buttonInteractArraySize= 3;
String buttonInteractArray[buttonInteractArraySize]= {"Tap", "Hold X Seconds", "Continuous Hold"};
const int objectiveArraySize= 5;
String objectiveArray[objectiveArraySize]= {"Both Countdown", "Both Countup", "Both Reset", "Pause/Countdown", "Reset/Countdown"};
byte teamRunDownClock;
int objectiveTime;
int gameLengthTime;
byte gameID;
int startDelayTimeMillis;
int holdXTime;
byte startAudio;
byte endAudio;
byte buttonInteraction;
byte objective;
int objectiveTimeBlue;
byte checkTeamTime;
int objectiveTimeRed;
byte limitGameLength;
byte enableOvertime;
byte timeExit;
String timeDirection;
byte enableRotaryEncoder;
int gameLengthTimeDisplay;
byte setUpGame;
byte turnLEDOff;
// -------------------- Start Global Code for Rotary Encoder -----------------------------
volatile boolean TurnDetected; // need volatile for Interrupts
volatile boolean rotationdirection; // CW or CCW rotation
const int PinCLK=2; // Generating interrupts using CLK signal
const int PinDT=3; // Reading DT signal
const int EncoderButton = 7; // Reading Push Button switch
//int RotaryPosition=0; // To store Stepper Motor Position
int RotaryValue;
//int RotaryPosition; // To store Stepper Motor Position
int PrevPosition; // Previous Rotary position Value to check accuracy
byte gameExitCheck;
//unsigned long startMillis; //some global variables available anywhere in the program
//------------- End Rotary Encoder ----------------------------------
void setup() {
Serial.begin(9600); // Better to use when debugging with the serial monitor
//Serial.begin(38400); // needed for mp3 player may cause issues in the serial monitor
mp3.begin(9600);// initiallze MP3
sendCommand(0x03, 0, kingofthehill);//Send command to play song 6
delay(3000);
pinMode(REDPIN, OUTPUT);
pinMode(GREENPIN, OUTPUT);
pinMode(BLUEPIN, OUTPUT);
pinMode(ledPinRed, OUTPUT); // identify Red LED Pin as output
pinMode(ledPinBlue, OUTPUT); // identify Blue LED pin as output
pinMode(buttonRedpin, INPUT_PULLUP); // Identify Red button as input
pinMode(buttonBluepin, INPUT_PULLUP); // Identify Blue button as input
// Set encoder pins and attach interrupts
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
pinMode(EncoderButton,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENC_A), read_encoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENC_B), read_encoder, CHANGE);
// Radio Reciever
radio.begin();
radio.openReadingPipe(0, address);
radio.setPALevel(RF24_PA_MIN);
// set up the LCD's number of columns and rows:
lcd.init(); // initialize the lcd
lcd.backlight();
// Print a message to the LCD.
displayLCD (0, 0, "Hello There!", "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
digitalWrite(ledPinRed, HIGH); // turn the red LED on
digitalWrite(ledPinBlue, HIGH); // turn the blue LED on
delay(delayLCD);
USBCheck ();
// Set each of the 7 segments to dashes
matrix.begin(0x70);
matrix.print(10000, DEC);
matrix.writeDisplay();
delay(250);
// Set each of the 7 segments to zero Remove?
int time_1 = 0; // Left time display
int time_2 = 0; // Middle left time display
int time_3 = 0; // Middle right time display
int time_4 = 0; // Right time display
//Remove ?? not sure where used
// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
// END of Trinket-specific code.
buttonCombinedFunc ("Use Rotry Encodr", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
Serial.println(RotaryValue);
enableRotaryEncoder = RotaryValue;
displayLCD (0, 0, "Loading..." , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
strip.begin(); // INITIALIZE NeoPixel LED strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(255); // Set BRIGHTNESS to max
colorLEDChange( 0, 255, 0);
delay(1000);
colorLEDChange( 255, 0, 0); // Red
delay(1000);
colorLEDChange( 0, 0, 255); // Blue
delay(1000);
//Save battery
turnLEDOff = 1;
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Standby LEDs Off", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
else{
rotaryCombinedFunc ("Standby LEDs Off", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
Serial.println("Turn LEDs Off?");
Serial.println(RotaryValue);
turnLEDOff = RotaryValue;
digitalWrite(ledPinRed, LOW); // turn the red LED on
digitalWrite(ledPinBlue, LOW); // turn the blue LED on
if (turnLEDOff == 0){
colorLEDChange( 0, 0, 0);
}
else{
colorLEDChange( 0, 255, 0);
}
setUpGame = 0;
}
void loop() {
if (setUpGame == 0){
adminSetup();
}
//parameterCheck();
//USBCheck ();
if (turnLEDOff == 0){
colorLEDChange( 0, 0, 0);
}
else{
colorLEDChange( 0, 255, 0);
}
teamInControl = "Green";
delay(1000);
inputLCDText = "Standby Mode";
displayLCD (0, 0, inputLCDText , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
inputLCDText = "Press R 2 Start";
displayLCD (0, 1, inputLCDText , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
//delay(delayLCD);
radio.startListening();
while(2>1){
if (digitalRead(buttonRedpin) == LOW){
radio.stopListening();
break; // exit loops
}
radio.read(&gogogo, sizeof(gogogo));
if (gogogo == 1) {
Serial.println("GameStarted");
radio.stopListening();
break; // exit loops
}
if((startAudio == 1) && (limitGameLength == 1)){
radio.stopListening();
displayLCD (0, 0, "Initializing" , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
break; // exit loops
}
}
colorLEDChange( 255, 0, 0); // Red
teamInControl = "Red";
delay(1000);
colorLEDChange( 0, 0, 255); // Blue
teamInControl = "Blue";
delay(1000);
colorLEDChange( 0, 255, 0);
teamInControl = "Green";
delay(1000);
if (turnLEDOff == 0){
colorLEDChange( 0, 0, 0);
}
if((gameSelectedMain == "Time Keeper") || (gameSelectedMain == "Attrition") || (gameSelectedMain == "Death Clicks")){
displayLCD (0, 0, "Initializing" , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
} else{
inputLCDText = " Red:" + String(teamTime.mRed) + String(teamTime.kRed) + ":" + String(teamTime.jRed) + String(teamTime.iRed);
displayLCD (0, 0, inputLCDText , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
inputLCDText = "Blue:" + String(teamTime.mBlue) + String(teamTime.kBlue) + ":" + String(teamTime.jBlue) + String(teamTime.iBlue);
displayLCD (0, 1, inputLCDText , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
if(limitGameLength == 0){
displayLCD (11, 0, "Game" , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
}
if (buttonMode == "Pause"){
if(runDownTeamColor == "Blue"){
inputLCDText = " Red:--:-- ";
displayLCD (0, 0, inputLCDText , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
}
else if (runDownTeamColor == "Red"){
inputLCDText = "Blue:--:-- ";
displayLCD (0, 1, inputLCDText , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
}
}
}
// Something wierd in the code is messing with the times and it was easier to just adjust it here
if (buttonMode == "Continuous")
{
teamTime.mBlue = timeOutput.mRed;
teamTime.kBlue = timeOutput.kRed;
teamTime.jBlue = timeOutput.jRed;
teamTime.iBlue = timeOutput.iRed;
teamTime.mRed = timeOutput.mBlue;
teamTime.kRed = timeOutput.kBlue;
teamTime.jRed = timeOutput.jBlue;
teamTime.iRed = timeOutput.iBlue;
Skip = "No";
}
// ----------------- Start Game Loop -----------------------------------
Serial.println("Gamelength check");
Serial.println(gameLengthMillis);
Serial.println("Gamestart check");
Serial.println(gameStartMillis);
if (startAudio == 0){
delay(startDelayTimeMillis);
sendCommand(0x03, 0, roundbegins);//Send command to play song 6
delay(7000);
}
else{
delay(startDelayTimeMillis);
}
gameStartMillis = millis();
if (gameSelectedMain == "Time Keeper")
{
inputLCDText = " Game";
displayLCD (0, 0, inputLCDText , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
overTime = "No";
currentSecondMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started). This is used to check when to increment the 7 segment display.
gameCheckMillis = gameLengthMillis - (currentSecondMillis - gameStartMillis);
//displayLCD (0, 1, String(gameCheckMillis/1000L) , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
gameCheckMillisCheck = gameCheckMillis;
while(2>1){
if ((digitalRead(buttonRedpin) == LOW) && (digitalRead(buttonBluepin) == LOW)) //Code used to edit the left digit, runs each time the red button gets hit when setting the time
{
break; // exit loops
} else if (gameTimeOver == "Yes"){
break; // exit loops
}
gameClock();
gameLengthDisplay ();
/*
if(gameCheckMillis < (gameCheckMillisCheck-1000L)){
displayLCD (0, 1, String(gameCheckMillis/1000L) , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
gameCheckMillisCheck = gameCheckMillis;
}
*/
}
//displayLCD (0, 1, "0" , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
}else if ((gameSelectedMain== "Attrition") || (gameSelectedMain== "Death Clicks")) {
funcAttrition ();
}
else
{
if ((buttonMode == "Tap") || (buttonMode == "Pause")){
while(2>1){
gameLengthDisplay ();
gameClock();
if (gameTimeOver == "Yes"){
break; // exit loops
}
if (digitalRead(buttonRedpin) == LOW){
funcX(buttonRedpin, "Default");
if (checkX == "Yes")
{
Serial.print("Red");
Serial.println(" Team Controls the Hill"); //Show which song is playing in serial monitor
sendCommand(0x03, 0, redteamhillcontrolled);//Send command to play song 6
colorLEDChange( 255, 0, 0); // Red
teamInControl = "Red";
//if ((runDownTeamColor == "Red") || (buttonMode == "Pause")){
if ((runDownTeamColor == "Red") ){
if (enableOvertime == 0){
overTime = "Yes";
}
}
delay(250);
Skip = "Yes";
if(variableX == "X")
{
checkX = "No";
}
else
{
checkX = "Yes";
}
break; // exit loops
}
}
if ((digitalRead(buttonBluepin) == LOW)){
funcX(buttonBluepin, "Default");
if (checkX == "Yes")
{
Serial.print("Blue");
Serial.println(" Team Controls the Hill"); //Show which song is playing in serial monitor
sendCommand(0x03, 0, blueteamhillcontrolled);//Send command to play song 6
colorLEDChange( 0, 0, 255); // Blue
teamInControl = "Blue";
//if ((runDownTeamColor == "Blue") || (buttonMode == "Pause")){
if ((runDownTeamColor == "Blue") ){
if (enableOvertime == 0){
overTime = "Yes";
}
}
delay(250);
Skip = "No";
if(variableX == "X")
{
checkX = "No";
}
else
{
checkX = "Yes";
}
break; // exit loops
}
}
}
}
while(2>1){
teamHold = 0;
gameLengthDisplay ();
gameClock();
theBugger(teamTime.mBlue,teamTime.kBlue,teamTime.jBlue,teamTime.iBlue, "Blue", "Before Loops");
theBugger(teamTime.mRed,teamTime.kRed,teamTime.jRed,teamTime.iRed, "Red", "Before Loops");
if(Skip == "No")
{
teamTime = funcTimeLoop(teamTime.mBlue,teamTime.kBlue,teamTime.jBlue,teamTime.iBlue,
timeCheck_1, timeCheck_2,
timeReset_1, timeReset_2, directionInput, "Red",redteamhillcontrolled,
ledPinRed, buttonRedpin, 0, ledPinBlue, teamTime.mRed,teamTime.kRed,teamTime.jRed,teamTime.iRed,buttonBluepin);
}
Skip = "No";
theBugger(teamTime.mBlue,teamTime.kBlue,teamTime.jBlue,teamTime.iBlue, "Blue", "Between Loops");
theBugger(teamTime.mRed,teamTime.kRed,teamTime.jRed,teamTime.iRed, "Red", "Between Loops");
if((teamTime.Victory == "Blue") || (gameTimeOver == "Yes")){
Serial.println("Blue Over");
break; // exit loops
}
gameLengthDisplay ();
gameClock();
teamTime = funcTimeLoop(teamTime.mRed,teamTime.kRed,teamTime.jRed,teamTime.iRed,
timeCheck_1, timeCheck_2,
timeReset_1, timeReset_2, directionInput, "Blue",blueteamhillcontrolled,
ledPinBlue, buttonBluepin, 0, ledPinRed,teamTime.mBlue,teamTime.kBlue,teamTime.jBlue,teamTime.iBlue,buttonRedpin);
if((teamTime.Victory == "Red") || (gameTimeOver == "Yes")){
Serial.println("Red Over");
break; // exit loops
}
gameLengthDisplay ();
gameClock();
if(gameTimeOver == "Yes")
{
break; // exit loops
}
}
}
// ----------------- End Game Loop -----------------------------------
// ----------------- Start Show Winner -------------------------------------
gameStartMillis = millis();
if(((teamTime.Victory == "Blue") && ((buttonMode == "Tap") || (buttonMode == "Pause"))) || ((teamTime.Victory == "Red") && (buttonMode == "Continuous")) ){
Serial.println("Game Over Blue Team Wins"); //Show which song is playing in serial monitor
sendCommand(0x03, 0, gameover);//Send command to play song 6
delay(1500); // add a delay to allow time for the button to be released
sendCommand(0x03, 0, blueteamwin);//Send command to play song 6
delay(2000); // add a delay to allow time for the button to be released
sendCommand(0x03, 0, stargatealarm);//Send command to play song 6
Serial.println("Stargate 1");
while(2>1){
digitalWrite(ledPinBlue, HIGH); // turn the red LED on
colorLEDChange( 0, 0, 255); // Blue
delay(250);
digitalWrite(ledPinBlue, LOW); // turn the blue LED off
colorLEDChange( 0, 0, 0); // Blank
delay(250);
gameStartMillis = millis();
while(2>1){
if ((digitalRead(buttonRedpin) == LOW) && (digitalRead(buttonBluepin) == LOW)) //Code used to edit the left digit, runs each time the red button gets hit when setting the time
{
currentSecondMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started). This is used to check when to increment the 7 segment display.
gameCheckMillis = currentSecondMillis - gameStartMillis;
if (gameCheckMillis > gameRestart)
{
time2Reset = "Yes";
break; // exit loops
}
}
else{
break; // exit loops
}
}
if(time2Reset == "Yes"){
time2Reset = "No";
break; // exit loops
}
}
}
if(((teamTime.Victory == "Red") && ((buttonMode == "Tap") || (buttonMode == "Pause"))) || ((teamTime.Victory == "Blue") && (buttonMode == "Continuous")) ){
Serial.println("Game Over Red Team Wins"); //Show which song is playing in serial monitor
sendCommand(0x03, 0, gameover);//Send command to play song 6
delay(1500); // add a delay to allow time for the button to be released
sendCommand(0x03, 0, redteamwin);//Send command to play song 6
delay(2000); // add a delay to allow time for the button to be released
sendCommand(0x03, 0, stargatealarm);//Send command to play song 6
Serial.println("Stargate 2");
while(2>1){
digitalWrite(ledPinRed, HIGH); // turn the red LED on
colorLEDChange( 255, 0, 0); // Red
delay(250);
digitalWrite(ledPinRed, LOW); // turn the blue LED off
colorLEDChange( 0, 0, 0); // Blank
delay(250);
gameStartMillis = millis();
while(2>1){
if ((digitalRead(buttonRedpin) == LOW) && (digitalRead(buttonBluepin) == LOW)) //Code used to edit the left digit, runs each time the red button gets hit when setting the time
{
currentSecondMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started). This is used to check when to increment the 7 segment display.
gameCheckMillis = currentSecondMillis - gameStartMillis;
if (gameCheckMillis > gameRestart)
{
time2Reset = "Yes";
break; // exit loops
}
}
else{
break; // exit loops
}
}
if(time2Reset == "Yes"){
time2Reset = "No";
break; // exit loops
}
}
}
if(gameTimeOver == "Yes")
{
//gameLengthMillis = timeOutput.mLimit*600L + timeOutput.kLimit*60L + timeOutput.jLimit*10L + timeOutput.iLimit;
//gameLengthMillis = gameLengthMillis*1000L;
radio.stopListening();
if (teamInControl == "Red"){
Score.teamInControl = 0;
/*
teamTime.mRed = teamTime.m;
teamTime.kRed = teamTime.k;
teamTime.jRed= teamTime.j;
teamTime.iRed = teamTime.i;
*/
} else
if (teamInControl == "Blue"){
Score.teamInControl = 1;
/*
teamTime.mBlue = teamTime.m;
teamTime.kBlue = teamTime.k;
teamTime.jBlue = teamTime.j;
teamTime.iBlue = teamTime.i;
*/
}
Score.timerName = 1;
//Score.blueTime = (teamTime.mBlue*-1)*600L + (long (teamTime.kBlue*-1))*60L + (long (teamTime.jBlue*-1))*10L + (long (teamTime.iBlue*-1));
//Score.redTime = (long (teamTime.mBlue*-1))*600L + (long (teamTime.kBlue*-1))*60L + (long (teamTime.jBlue*-1))*10L + (long (teamTime.iBlue*-1));
Score.blueTime = (teamTime.mBlue*600 + teamTime.kBlue*60 + teamTime.jBlue*10 + teamTime.iBlue)*-1;
Score.redTime = (teamTime.mRed*600 + teamTime.kRed*60 + teamTime.jRed*10 + teamTime.iRed)*-1;
//Score.timerName = 0;
//Score.blueTime = 754;
//Score.redTime =754;
//Score.teamInControl = 1;
//Score.blueTime = Score.blueTime*2;
Serial.println("Game Over Check Time"); //Show which song is playing in serial monitor
sendCommand(0x03, 0, stargatealarm);//Send command to play song 6
while(2>1){
radio.write(&Score, sizeof(Scorekeeper));
delay(500);
//displayLCD (0, 0, String(Score.timerName), "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
//displayLCD (5, 0, String(Score.blueTime), "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
//displayLCD (0, 1, String(Score.teamInControl), "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
//displayLCD (5, 1, String(Score.redTime), "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
Serial.println(Score.timerName);
Serial.println(String(Score.blueTime));
Serial.println(String(Score.redTime));
Serial.println(Score.teamInControl);
colorLEDChange( 0, 255, 0);
delay(250);
if (teamInControl == "Red"){
colorLEDChange( 255, 0, 0); //
delay(400);
} else
if (teamInControl == "Blue"){
colorLEDChange( 0, 0, 255); //
delay(400);
} else{
colorLEDChange( 0, 0, 0); // Blank
delay(250);
}
gameStartMillis = millis();
while(2>1){
if ((digitalRead(buttonRedpin) == LOW) && (digitalRead(buttonBluepin) == LOW)) //Code used to edit the left digit, runs each time the red button gets hit when setting the time
{
currentSecondMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started). This is used to check when to increment the 7 segment display.
gameCheckMillis = currentSecondMillis - gameStartMillis;
if (gameCheckMillis > gameRestart)
{
time2Reset = "Yes";
break; // exit loops
}
}
else{
break; // exit loops
}
}
if(time2Reset == "Yes"){
time2Reset = "No";
break; // exit loops
}
}
}
//--------------------- Reset variables
teamTime = timeOutput;
// Set each of the 7 segments to zero
int time_1 = 0; // Left time display
int time_2 = 0; // Middle left time display
int time_3 = 0; // Middle right time display
int time_4 = 0; // Right time display
gameClockIndex = 12;
gameClockSound = 27;
//Attrition
redLifeCount = startLifeCount;
blueLifeCount = startLifeCount;
attritionLifeIndex = 3 - attritionLifeSoundModifier;
attritionLifeSound = 33 - attritionLifeSoundModifier;
alarmCheck = "Yes";
if(variableX == "X")
{
checkX = "No";
}
else
{
checkX = "Yes";
}
if(runDownTeamColor == "Red"){
runDownTeamColor = "Blue";
teamTime.mBlue = timeOutput.mRed;
teamTime.kBlue = timeOutput.kRed;
teamTime.jBlue = timeOutput.jRed;
teamTime.iBlue = timeOutput.iRed;
teamTime.mRed = timeOutput.mBlue;
teamTime.kRed = timeOutput.kBlue;
teamTime.jRed = timeOutput.jBlue;
teamTime.iRed = timeOutput.iBlue;
timeOutput = teamTime;
}
else if(runDownTeamColor == "Blue"){
runDownTeamColor = "Red";
teamTime.mBlue = timeOutput.mRed;
teamTime.kBlue = timeOutput.kRed;
teamTime.jBlue = timeOutput.jRed;
teamTime.iBlue = timeOutput.iRed;
teamTime.mRed = timeOutput.mBlue;
teamTime.kRed = timeOutput.kBlue;
teamTime.jRed = timeOutput.jBlue;
teamTime.iRed = timeOutput.iBlue;
timeOutput = teamTime;
}
gameTimeOver = "No";
overTime = "No";
overTimeStart = "Yes";
digitalWrite(ledPinBlue, LOW); // turn the blue LED off
digitalWrite(ledPinRed, LOW); // turn the blue LED off
displayLCD (0, 0, "Switch Game Mode" , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
delay(1500);
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Switch Game Mode", "Loading...", 1, 1, "list", YesNoArray, YesNoArraySize);
}
else{
rotaryCombinedFunc ("Switch Game Mode", "Loading...", 1, 1, "list", YesNoArray, YesNoArraySize);
}
Serial.println("Button Interaction");
Serial.println(RotaryValue);
setUpGame = RotaryValue;
//-------------------- End Main Loop
}
// ----------Functions -----------------
void globalTransceiver () {
//Radio Reciever Code
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
int gogogo = 0;
RF24 radio(48, 46); // CE, CSN
const byte address[6] = "T0001";
//End Radio Reciever Code
}
void setupTransceiver (){
// Radio Reciever
radio.begin();
radio.openReadingPipe(0, address);
radio.setPALevel(RF24_PA_MIN);
}
void startGameTransceiver () {
radio.read(&gogogo, sizeof(gogogo));
if (gogogo == 1) {
Serial.println("GameStarted");
radio.stopListening();
//break; // exit loops
}
}
void gameClock(){
currentSecondMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started). This is used to check when to increment the 7 segment display.
gameCheckMillis = currentSecondMillis - gameStartMillis;
Serial.println("gameCheckMillis = ");
Serial.print(gameCheckMillis);
Serial.println("gameLengthMillis = ");
Serial.print(gameLengthMillis);
if (gameCheckMillis > gameLengthMillis)
{
if(overTime == "No")
{
gameTimeOver = "Yes";
Serial.println("gameTimeOver = Yes");
}
else if (overTime == "Yes" && overTimeStart == "Yes")
{
overTimeStart = "No";
Serial.println("Game is in Over Time");
sendCommand(0x03, 0, overTimeSound);//Send command to play song 6
}
}
currentSecondMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started). This is used to check when to increment the 7 segment display.
gameCheckMillis = gameLengthMillis - (currentSecondMillis - gameStartMillis);
if ((gameCheckMillis < gameClockArray[gameClockIndex]))
{
if ((gameClockSound == 15) && (overTime == "No")){
sendCommand(0x03, 0, stargatealarm);//Send command to play song 6
Serial.println("Stargate 3");
Serial.println(overTime);
gameTimeOver = "Yes";
Serial.println(gameClockSound);
Serial.println("Game Time Over");
}
else if ((gameClockSound > 15) &&(endAudio == 0)) {
Serial.println(gameCheckMillis);
Serial.println(gameClockIndex);
Serial.println(gameClockSound);
sendCommand(0x03, 0, gameClockSound);//Send command to play song 6
}
if (gameClockSound > 15){
gameClockIndex = gameClockIndex -1;
gameClockSound = gameClockSound -1;
}
}
}
void theBugger(int m, int k, int j, int i, String teamName, String functionName) {
//display_freeram();
//theBugger(m, k, j, i, teamColor, "funcTimeLoop");
Serial.print(functionName);
Serial.print(" ");
Serial.print(teamName);
Serial.print(" ");
Serial.print(m);
Serial.print(k);
Serial.print(":");
Serial.print(j);
Serial.println(i);
}
void display_freeram() {
Serial.print(F("- SRAM left: "));
Serial.println(freeRam());
}
int freeRam() {
extern int __heap_start,*__brkval;
int v;
return (int)&v - (__brkval == 0
? (int)&__heap_start : (int) __brkval);
}
//3 Pin LED strip
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void colorLEDChange( int redSetting, int greenSetting, int blueSetting){
//4 Pin LED Strip
analogWrite(REDPIN, redSetting);
analogWrite(GREENPIN, greenSetting);
analogWrite(BLUEPIN, blueSetting);
// 3 Pin LED Strip
colorWipe(strip.Color( redSetting, greenSetting, blueSetting), 0); // Green
}
// ------------- Start Time Keeper ------------------------------------------------------
void simpleTimerSetup () {
overTime = "No";
currentSecondMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started). This is used to check when to increment the 7 segment display.
gameCheckMillis = gameLengthMillis - (currentSecondMillis - gameStartMillis);
gameCheckMillisCheck = gameCheckMillis;
}
void simpleTimer () {
gameClock();
Serial.println("gameCheckMillis2 = ");
Serial.print(gameCheckMillis);
Serial.println("gameCheckMillisCheck = ");
Serial.print(gameCheckMillisCheck);
if(gameCheckMillis < (gameCheckMillisCheck-1000L)){
//displayLCD (0, 1, String(gameCheckMillis/1000L) , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
gameCheckMillisCheck = gameCheckMillis;
}
if((gameTimeOver == "Yes") && (alarmCheck == "Yes")){
sendCommand(0x03, 0, stargatealarm);
alarmCheck = "No";
}
}
// ------------- Attrition -----------------------------
void funcAttrition (){
if (directionInput == 1)
{ sendCommand(0x03, 0, attritionsound);//Send command to play song 6
}
// Setup
if ((runDownTeamColor == "Red") && (directionInput == 1))
{
displayLCD (0, 0, "Red Team Lives" , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
inputLCDText = "Remaining " + String(redLifeCount);
displayLCD (0, 1, inputLCDText , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
matrix.print(redLifeCount, DEC);
matrix.drawColon(true);
matrix.writeDisplay();
} else if ((runDownTeamColor == "Red") && (directionInput == -1))
{
displayLCD (0, 0, "Red Team Number" , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
inputLCDText = "of Deaths " + String(redLifeCount);
displayLCD (0, 1, inputLCDText , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
matrix.print(redLifeCount, DEC);
matrix.drawColon(true);
matrix.writeDisplay();
}else if ((runDownTeamColor == "Blue") && (directionInput == 1))
{
displayLCD (0, 0, "Blue Team Lives" , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
inputLCDText = "Remaining " + String(blueLifeCount);
displayLCD (0, 1, inputLCDText , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
matrix.print(blueLifeCount, DEC);
matrix.drawColon(true);
matrix.writeDisplay();
} else if ((runDownTeamColor == "Blue") && (directionInput == -1))
{
displayLCD (0, 0, "Blue Team Number" , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
inputLCDText = "of Deaths " + String(blueLifeCount);
displayLCD (0, 1, inputLCDText , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
matrix.print(blueLifeCount, DEC);
matrix.drawColon(true);
matrix.writeDisplay();
}
if (runDownTeamColor == "Red")
{
colorLEDChange( 255, 0, 0); // Red
}
else {
colorLEDChange( 0, 0, 255); // Blue
}
simpleTimerSetup ();
// Loop
while(2>1){
simpleTimer ();
if ((runDownTeamColor == "Red") && (digitalRead(buttonRedpin) == LOW))
{
redLifeCount = funcLifeCount("Red", directionInput, redLifeCount);
colorLEDChange( 0, 0, 0); // Red
delay(250);
colorLEDChange( 255, 0, 0); // Red
if ((redLifeCount == 0) && (directionInput == 1)){
teamInControl = "Red";
break; //
}
} else if ((runDownTeamColor == "Blue") && (digitalRead(buttonBluepin) == LOW))
{
blueLifeCount = funcLifeCount("Blue", directionInput, blueLifeCount);
colorLEDChange( 0, 0, 0); // Red
delay(250);
colorLEDChange( 0, 0, 255); // Red
if ((blueLifeCount == 0) && (directionInput == 1)){
teamInControl = "Blue";
break; //
}
}
gameStartMillis2 = millis();
while(2>1){
if ((digitalRead(buttonRedpin) == LOW) && (digitalRead(buttonBluepin) == LOW)) //Code used to edit the left digit, runs each time the red button gets hit when setting the time
{
currentSecondMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started). This is used to check when to increment the 7 segment display.
gameCheckMillis2 = currentSecondMillis - gameStartMillis2;
if (gameCheckMillis2 > gameRestart)
{
time2Reset = "Yes";
break; // exit loops
}
}
else{
break; // exit loops
}
}
if(time2Reset == "Yes"){
//time2Reset = "No";
break; // exit loops
}
}
gameTimeOver = "Yes";
}
int funcLifeCount(int teamColor, int direction, int lifeCount){
int lifeCounter;
lifeCounter = lifeCount - direction;
if (direction == 1)
{
inputLCDText = "Remaining " + String(lifeCounter);
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
matrix.print(lifeCounter, DEC);
matrix.drawColon(true);
matrix.writeDisplay();
funcAttritionSound(lifeCounter);
} else if (direction == -1)
{
inputLCDText = "of Deaths " + String(lifeCounter);
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
matrix.print(lifeCounter, DEC);
matrix.drawColon(true);
matrix.writeDisplay();
}
return lifeCounter;
}
int funcAttritionSound(int lifeCounter){
if ((lifeCounter < gameAttritionArray[attritionLifeIndex]))
{
if (lifeCounter == 0){
sendCommand(0x03, 0, noLivesSound);//Send command to play song 6
delay(1500);
}
else {
sendCommand(0x03, 0, attritionLifeSound);//Send command to play song 6
}
attritionLifeIndex = attritionLifeIndex -1;
attritionLifeSound = attritionLifeSound -1;
}
}
// ------------- End Attrition ------------------------
// ------------- Timer Loop Functions --------------------------------------------------------
tClock funcTimeLoop(int time_1, int time_2, int time_3,int time_4, int timeCheck_1, int timeCheck_2,
int timeReset_1, int timeReset_2, int direction, String teamColor,int teamhillcontrolled,
int teamPin, int teamButton, int teamReset, int oTeamPin, int em, int ek, int ej, int ei, int oTeamButton)
{
tClock tInput;
tInput.loopExit = "No";
// This is probably very inefficient but these loops are what calculate what to display on the 7 segment digits
for(int m = time_1; m >= timeCheck_1; m--){ //increments the left digit, m-- is the same as m = m - 1, it essentialy decreases the value of the left digit by 1 each time this loop runs
for(int k = time_2; k >= timeCheck_1; k--){ //increments the left digit, k-- is the same as k = k - 1, it essentialy decreases the value of the middle left digit by 1 each time this loop runs
for(int j = time_3; j >= timeCheck_2; j--){ //increments the left digit, j-- is the same as j = j - 1, it essentialy decreases the value of the middle right digit by 1 each time this loop runs
for(int i = time_4; i >= timeCheck_1; i--) {
theBugger(m, k, j, i, teamColor, "funcTimeLoop");
gameLengthDisplay ();
tInput = funcTimeButtonCheck(teamColor, teamhillcontrolled, teamPin, teamButton, teamReset,
oTeamPin, tInput, direction, m, k, j, i, em, ek, ej, ei,oTeamButton);
if (tInput.loopExit == "Yes")
{break; // exit loops
}
}
if (tInput.loopExit == "Yes")
{break; // exit loops
}
time_4 = timeReset_1; // reset the right digit once it gets to zero
}
if (tInput.loopExit == "Yes")
{break; // exit loops
}
time_3 = timeReset_2; // reset the middle right digit once it gets to zero (note this is 5 because there are only 60 seconds in a minute
}
if (tInput.loopExit == "Yes")
{break; // exit loops
}
time_2 = timeReset_1; // reset the right digit once it gets to zero
}
// End of for loop
return tInput;
}
tClock funcTimeButtonCheck(String teamColor,int teamhillcontrolled, int teamPin, int teamButton, int teamReset, int oTeamPin,tClock tInput, int direction, int m, int k, int j, int i,int em, int ek, int ej, int ei, int oTeamButton )
{
theBugger(m, k, j, i, teamColor, "funcTimeButtonCheck");
if (buttonMode == "Pause")
{
if (runDownTeamColor == teamColor)
{
Serial.println(runDownTeamColor);
Serial.println(teamColor);
Serial.println("runDownTeamColor == teamColor");
}
else
{
Serial.println(runDownTeamColor);
Serial.println(teamColor);
Serial.println("runDownTeamColor does not = teamColor");
Serial.print("gameClockSound = ");
Serial.println(gameClockSound);
if (gameClockSound > 15){
Serial.print("gameClockSoundCheck = ");
Serial.println(gameClockSound);
gameClock();
}
displayTime (m,k,j,i, direction,teamColor);
}
}
else
{
displayTime (m,k,j,i, direction,teamColor);
}
//---------------------------
// Need to DeleteNew Code for calculating score with remote
if (teamInControl == "Red"){
teamTime.mRed = m;
teamTime.kRed = k;
teamTime.jRed = j;
teamTime.iRed = i;
} else
if (teamInControl == "Blue"){
teamTime.mBlue = m;
teamTime.kBlue = k;
teamTime.jBlue = j;
teamTime.iBlue = i;
}
//-------------------------------------
startSecondMillis = millis(); // record the current time (actually the number of milliseconds since the program started). This variable is used to check whether 1 second has passed.
currentSecondMillis = millis(); //record the current "time" (actually the number of milliseconds since the program started). This is really just initializing this variable
// This loop checks to see whether 1 second has passed, so that it knows when to increment the 7 segment display
for(; currentSecondMillis - startSecondMillis < periodSecond;){ // exit the loop once the difference between the current time and the start of the loop is greater than a second
if (buttonMode == "Continuous")
{
tInput = funcCheckButtonHoldContinuous (teamColor,teamhillcontrolled, teamPin, teamButton, teamReset, oTeamPin,tInput, direction, m, k, j, i, em, ek, ej, ei);
}
else if (buttonMode == "Tap")
{
tInput = funcCheckButtonTap (teamColor,teamhillcontrolled, teamPin, teamButton, teamReset, oTeamPin,tInput, direction, m, k, j, i, em, ek, ej, ei,oTeamButton);
}
else if (buttonMode == "Pause")
{
tInput = funcCheckButtonTapPause (teamColor,teamhillcontrolled, teamPin, teamButton, teamReset, oTeamPin,tInput, direction, m, k, j, i, em, ek, ej, ei,oTeamButton);
}
//Need to add Button Reset capability
if (tInput.loopExit == "Yes")
{break; // exit loops
}
gameClock();
if(gameTimeOver == "Yes")
{
tInput.loopExit = "Yes";
break; // exit loops
}
}
return tInput;
}
// -------------- Specific Game Modes ------------------------
tClock funcCheckButtonTap (String teamColor,int teamhillcontrolled, int teamPin, int teamButton, int teamReset, int oTeamPin,tClock tInput, int direction, int m, int k, int j, int i, int em, int ek, int ej, int ei,int oTeamButton)
{
if ((digitalRead(teamPin) == LOW) && (digitalRead(teamButton) == LOW)) //this code runs when the red LED is off, the red button is pushed and the red button hasn't been pushed twice in a row
{
funcX(teamButton, teamColor);
if (checkX == "Yes")
{
theBugger(m, k, j, i, teamColor, "funcCheckButtonTap");
Serial.print(teamColor);
Serial.println(" Team Controls the Hill"); //Show which song is playing in serial monitor
sendCommand(0x03, 0, teamhillcontrolled);//Send command to play song 6
startMillis = millis(); //record what time the button was hit
digitalWrite(teamPin, HIGH); // turn the red LED on
digitalWrite(oTeamPin, LOW); // turn the blue LED off
// Set the color of the NeoPixel LED Strip
if (teamColor == "Red")
{
colorLEDChange( 255, 0, 0); // Red
teamInControl = "Red";
// save the blue teams
tInput.mRed = em;
tInput.kRed = ek;
tInput.jRed = ej;
tInput.iRed = ei;
// save the blue teams
if(checkReset == "Yes")
{
tInput.mBlue = timeOutput.mBlue;
tInput.kBlue = timeOutput.kBlue;
tInput.jBlue = timeOutput.jBlue;
tInput.iBlue = timeOutput.iBlue;
} else{
tInput.mBlue = m;
tInput.kBlue = k;
tInput.jBlue = j;
tInput.iBlue = i;
}
}
else
{
theBugger(m, k, j, i, teamColor, "funcCheckButtonTap");
colorLEDChange( 0, 0, 255); // blue
teamInControl = "Blue";
// save the red teams time
tInput.mBlue = em;
tInput.kBlue = ek;
tInput.jBlue = ej;
tInput.iBlue = ei;
// save the red teams
if(checkReset == "Yes")
{
tInput.mRed = timeOutput.mRed;
tInput.kRed = timeOutput.kRed;
tInput.jRed = timeOutput.jRed;
tInput.iRed = timeOutput.iRed;
}
else{
tInput.mRed = m;
tInput.kRed = k;
tInput.jRed = j;
tInput.iRed = i;
}
}
delay(250); // add a delay to allow time for the button to be released
tInput.loopExit = "Yes";
if(variableX == "X")
{
checkX = "No";
}
else
{
checkX = "Yes";
}
}
}
if(direction == 1)
{
if((m+k+j+i == 0) && (teamColor == "Blue")){
tInput.loopExit = "Yes";
tInput.Victory = "Red";
}
if((m+k+j+i == 0) && (teamColor == "Red")){
tInput.loopExit = "Yes";
tInput.Victory = "Blue";
}
}
return tInput;
}
tClock funcCheckButtonHoldContinuous (String teamColor,int teamhillcontrolled, int teamPin, int teamButton, int teamReset, int oTeamPin,tClock tInput, int direction, int m, int k, int j, int i, int em, int ek, int ej, int ei){
if (digitalRead(teamButton) == LOW && (teamHold == 0)) //this code runs when the red LED is off, the red button is pushed and the red button hasn't been pushed twice in a row
{
theBugger(m, k, j, i, teamColor, "funcCheckButtonHoldContinuous 1");
sendCommand(0x03, 0, teamhillcontrolled);//Send command to play song 6
startMillis = millis(); //record what time the button was hit
digitalWrite(teamPin, HIGH); // turn the red LED on
digitalWrite(oTeamPin, LOW); // turn the blue LED off
// Set the color of the NeoPixel LED Strip
if (teamColor == "Red")
{
colorLEDChange( 255, 0, 0); // Red
teamInControl = "Red";
}
else
{
colorLEDChange( 0, 0, 255); // blue
teamInControl = "Blue";
}
delay(250); // add a delay to allow time for the button to be released
teamHold = 1;
holdHillContested = 1;
}
if (digitalRead(teamButton) == HIGH)
{
theBugger(m, k, j, i, teamColor, "funcCheckButtonHoldContinuous 2");
teamHold = 0;
colorLEDChange( 0, 255, 0);
teamInControl = "Green";
if (holdHillContested == 1)
{
sendCommand(0x03, 0, hillcontested);//Send command to play song 6
holdHillContested = 0;
}
tInput.loopExit = "Yes";
if (teamColor == "Red")
{
// save the blue teams time
theBugger(m, k, j, i, teamColor, "Befor Save Time 1");
tInput.mBlue = m;
tInput.kBlue = k;
tInput.jBlue = j;
tInput.iBlue = i;
tInput.mRed = em;
tInput.kRed = ek;
tInput.jRed = ej;
tInput.iRed = ei;
theBugger(m, k, j, i, teamColor, "After Save Time 1");
theBugger(tInput.mBlue, tInput.kBlue, tInput.jBlue, tInput.iBlue, teamColor, "After Save Time 2");
}
else
{
// save the red teams time
theBugger(m, k, j, i, teamColor, "Befor Save Time 1");
tInput.mRed = m;
tInput.kRed = k;
tInput.jRed = j;
tInput.iRed = i;
theBugger(m, k, j, i, teamColor, "After Save Time 1");
theBugger(tInput.mBlue, tInput.kBlue, tInput.jBlue, tInput.iBlue, teamColor, "After Save Time 2");
}
}
if(direction == 1)
{
if((m+k+j+i == 0) && (teamColor == "Blue")){
tInput.loopExit = "Yes";
tInput.Victory = "Red";
}
if((m+k+j+i == 0) && (teamColor == "Red")){
tInput.loopExit = "Yes";
tInput.Victory = "Blue";
}
}
return tInput;
}
// -------------- End Continuously Hold -----------------------
//--------------- Start Hold X --------------------------------
void funcX(int teamButton, String teamColor)
{
if (variableX == "X")
{
holdHillContested = 1;
xStartMillis = millis();
while(2>1){
currentSecondMillis = millis();
xCheckMillis = currentSecondMillis - xStartMillis;
if (digitalRead(teamButton) == LOW)
{
if (holdHillContested == 1)
{
sendCommand(0x03, 0, hillcontested);//Send command to play song 6
holdHillContested = 0;
colorLEDChange( 244, 232, 104); // Gold
}
if (xCheckMillis > xLengthMillis)
{
checkX = "Yes";
break; // exit loops
}
}
else
{
if (teamColor == "Red")
{
sendCommand(0x03, 0, blueteamhillcontrolled);//Send command to play song 6
colorLEDChange( 0, 0, 255); // blue
teamInControl = "Blue";
}
else if (teamColor == "Blue")
{
sendCommand(0x03, 0, redteamhillcontrolled);//Send command to play song 6
colorLEDChange( 255, 0, 0); // red
teamInControl = "Red";
}
else
{
sendCommand(0x03, 0, hillcontested);//Send command to play song 6
colorLEDChange( 0, 255, 0);
teamInControl = "Green";
}
checkX = "No";
break; // exit loops
}
gameLengthDisplay ();
}
}
}
//--------------- End Hold X ----------------------------------
//--------------- Start Pause Timer ---------------------------------
tClock funcCheckButtonTapPause (String teamColor,int teamhillcontrolled, int teamPin, int teamButton, int teamReset, int oTeamPin,tClock tInput, int direction, int m, int k, int j, int i, int em, int ek, int ej, int ei,int oTeamButton)
{
if ((digitalRead(teamPin) == LOW) && (digitalRead(teamButton) == LOW)) //this code runs when the red LED is off, the red button is pushed and the red button hasn't been pushed twice in a row
{
funcX(teamButton, teamColor);
if (checkX == "Yes")
{
theBugger(m, k, j, i, teamColor, "funcCheckButtonTap");
Serial.print(teamColor);
Serial.println(" Team Controls the Hill"); //Show which song is playing in serial monitor
sendCommand(0x03, 0, teamhillcontrolled);//Send command to play song 6
startMillis = millis(); //record what time the button was hit
digitalWrite(teamPin, HIGH); // turn the red LED on
digitalWrite(oTeamPin, LOW); // turn the blue LED off
// Set the color of the NeoPixel LED Strip
if (runDownTeamColor == "Red")
{
if (teamColor == "Red")
{
colorLEDChange( 255, 0, 0); // Red
teamInControl = "Red";
// save the blue teams
tInput.mRed = em;
tInput.kRed = ek;
tInput.jRed = ej;
tInput.iRed = ei;
// save the blue teams
tInput.mBlue = 9;
tInput.kBlue = 9;
tInput.jBlue = 9;
tInput.iBlue = 9;
if (enableOvertime == 0){
overTime = "Yes";
}
}
else
{
theBugger(m, k, j, i, teamColor, "funcCheckButtonTap");
colorLEDChange( 0, 0, 255); // blue
teamInControl = "Blue";
// save the red teams time
tInput.mBlue = em;
tInput.kBlue = ek;
tInput.jBlue = ej;
tInput.iBlue = ei;
// save the red teams
if(checkReset == "Yes")
{
tInput.mRed = timeOutput.mRed;
tInput.kRed = timeOutput.kRed;
tInput.jRed = timeOutput.jRed;
tInput.iRed = timeOutput.iRed;
}
else{
tInput.mRed = m;
tInput.kRed = k;
tInput.jRed = j;
tInput.iRed = i;
}
overTime = "No";
}
}
else
{
if (teamColor == "Red")
{
colorLEDChange( 255, 0, 0); // Red
teamInControl = "Red";
// save the blue teams
tInput.mRed = em;
tInput.kRed = ek;
tInput.jRed = ej;
tInput.iRed = ei;
// save the blue teams
if(checkReset == "Yes")
{
tInput.mBlue = timeOutput.mBlue;
tInput.kBlue = timeOutput.kBlue;
tInput.jBlue = timeOutput.jBlue;
tInput.iBlue = timeOutput.iBlue;
} else{
tInput.mBlue = m;
tInput.kBlue = k;
tInput.jBlue = j;
tInput.iBlue = i;
}
overTime = "No";
}
else
{
theBugger(m, k, j, i, teamColor, "funcCheckButtonTap");
colorLEDChange( 0, 0, 255); // blue
teamInControl = "Blue";
// save the red teams time
tInput.mBlue = em;
tInput.kBlue = ek;
tInput.jBlue = ej;
tInput.iBlue = ei;
// save the red teams
tInput.mRed = 9;
tInput.kRed = 9;
tInput.jRed = 9;
tInput.iRed = 9;
if (enableOvertime == 0){
overTime = "Yes";
}
}
}
delay(250); // add a delay to allow time for the button to be released
tInput.loopExit = "Yes";
if(variableX == "X")
{
checkX = "No";
}
else
{
checkX = "Yes";
}
}
}
if(direction == 1)
{
if((m+k+j+i == 0) && (teamColor == "Blue")){
tInput.loopExit = "Yes";
tInput.Victory = "Red";
}
if((m+k+j+i == 0) && (teamColor == "Red")){
tInput.loopExit = "Yes";
tInput.Victory = "Blue";
}
}
return tInput;
}
//--------------- End Pause Timer -----------------------------
// -------------- End Specific Game Modes --------------------
void changeTeamColor(String teamColor, int teamButton, int teamPin, int oTeamPin){
if (buttonMode == "Continuous") //this code runs when the red LED is off, the red button is pushed and the red button hasn't been pushed twice in a row
{
theBugger(9, 9, 9, 9, teamColor, "changeTeamColor");
digitalWrite(teamPin, HIGH); // turn the red LED on
digitalWrite(oTeamPin, LOW); // turn the blue LED off
// Set the color of the NeoPixel LED Strip
if (teamColor == "Red")
{
colorLEDChange( 255, 0, 0); // Red
teamInControl = "Red";
}
else
{
colorLEDChange( 0, 0, 255); // blue
teamInControl = "Blue";
}
}
}
int displayTime (int m, int k, int j, int i,int direction, String teamColor)
{
//Tell the 7 segment display what number to display for each digit
theBugger(m, k, j, i, teamColor, "displayTime");
int teamColorLCD;
if (buttonMode == "Continuous")
{
if(teamColor == "Red")
{
teamColorLCD = 0;
}
if(teamColor == "Blue")
{
teamColorLCD = 1;
}
}
if ((buttonMode == "Tap") || (buttonMode == "Pause"))
{
if(teamColor == "Red")
{
teamColorLCD = 1;
}
if(teamColor == "Blue")
{
teamColorLCD = 0;
}
}
int Clock_show = (m*1000+k*100+j*10+i)*direction;
matrix.print(Clock_show, DEC);
matrix.drawColon(true);
matrix.writeDisplay();
Serial.print(m*direction); // Left digit
Serial.print(k*direction); // Middle left digit
Serial.print(":"); // turn on the colon
Serial.print(j*direction); // Middle right digit
Serial.println(i*direction); // Right digit
lcd.setCursor(5, teamColorLCD);//lcd.setCursor(lcdLine1Start, lcdLineNum)
lcd.print(String(m*direction) + String(k*direction) + ":" + String(j*direction) + String(i*direction));
}
int displayLCD (int digit, int line, String lcdText, String lineClear)
{
//theBugger(9, 9, 9, 9, "Unknown", "displayLCD");
if(lineClear == "None")
{
}
else if(lineClear == "First")
{
lcd.setCursor(0, 0);//lcd.setCursor(lcdLine1Start, lcdLineNum)
lcd.print(" ");// clears previous display
}
else if(lineClear == "Second")
{
lcd.setCursor(0, 1);//lcd.setCursor(lcdLine1Start, lcdLineNum)
lcd.print(" ");// clears previous display
}
else
{
lcd.setCursor(0, 0);//lcd.setCursor(lcdLine1Start, lcdLineNum)
lcd.print(" ");// clears previous display
lcd.setCursor(0, 1);//lcd.setCursor(lcdLine1Start, lcdLineNum)
lcd.print(" ");// clears previous display
}
lcd.setCursor(digit, line);//lcd.setCursor(lcdLine1Start, lcdLineNum)
lcd.print(lcdText);
}
//-------------- End Timer Loop Functions
// --------------------- MP3 Functions ---------------------------------------------
void sendMP3Command(char c) {
//theBugger(9, 9, 9, 9, "Unknown", "sendMP3Command");
switch (c) {
case '?':
case 'h':
Serial.println("HELP ");
Serial.println(" p = Play");
Serial.println(" P = Pause");
Serial.println(" > = Next");
Serial.println(" < = Previous");
Serial.println(" s = Stop Play");
Serial.println(" + = Volume UP");
Serial.println(" - = Volume DOWN");
Serial.println(" c = Query current file");
Serial.println(" q = Query status");
Serial.println(" v = Query volume");
Serial.println(" x = Query folder count");
Serial.println(" t = Query total file count");
Serial.println(" f = Play folder 1.");
Serial.println(" S = Sleep");
Serial.println(" W = Wake up");
Serial.println(" r = Reset");
break;
case 'p':
Serial.println("Play ");
sendCommand(CMD_PLAY);
break;
case 'P':
Serial.println("Pause");
sendCommand(CMD_PAUSE);
break;
case '>':
Serial.println("Next");
sendCommand(CMD_NEXT_SONG);
sendCommand(CMD_PLAYING_N); // ask for the number of file is playing
break;
case '<':
Serial.println("Previous");
sendCommand(CMD_PREV_SONG);
sendCommand(CMD_PLAYING_N); // ask for the number of file is playing
break;
case 's':
Serial.println("Stop Play");
sendCommand(CMD_STOP_PLAY);
break;
case '+':
Serial.println("Volume Up");
sendCommand(CMD_VOLUME_UP);
break;
case '-':
Serial.println("Volume Down");
sendCommand(CMD_VOLUME_DOWN);
break;
case 'c':
Serial.println("Query current file");
sendCommand(CMD_PLAYING_N);
break;
case 'q':
Serial.println("Query status");
sendCommand(CMD_QUERY_STATUS);
break;
case 'v':
Serial.println("Query volume");
sendCommand(CMD_QUERY_VOLUME);
break;
case 'x':
Serial.println("Query folder count");
sendCommand(CMD_QUERY_FLDR_COUNT);
break;
case 't':
Serial.println("Query total file count");
sendCommand(CMD_QUERY_TOT_TRACKS);
break;
case 'f':
Serial.println("Playing folder 1");
sendCommand(CMD_FOLDER_CYCLE, 1, 0);
break;
case 'S':
Serial.println("Sleep");
sendCommand(CMD_SLEEP_MODE);
break;
case 'W':
Serial.println("Wake up");
sendCommand(CMD_WAKE_UP);
break;
case 'r':
Serial.println("Reset");
sendCommand(CMD_RESET);
break;
}
}
/********************************************************************************/
/*Function decodeMP3Answer: Decode MP3 answer. */
/*Parameter:-void */
/*Return: The */
String decodeMP3Answer() {
String decodedMP3Answer = "";
//theBugger(9, 9, 9, 9, "Unknown", "decodeMP3Answer");
decodedMP3Answer += sanswer();
switch (ansbuf[3]) {
case 0x3A:
decodedMP3Answer += " -> Memory card inserted.";
break;
case 0x3D:
decodedMP3Answer += " -> Completed play num " + String(ansbuf[6], DEC);
//sendCommand(CMD_NEXT_SONG);
//sendCommand(CMD_PLAYING_N); // ask for the number of file is playing
break;
case 0x40:
decodedMP3Answer += " -> Error";
break;
case 0x41:
decodedMP3Answer += " -> Data recived correctly. ";
break;
case 0x42:
decodedMP3Answer += " -> Status playing: " + String(ansbuf[6], DEC);
break;
case 0x48:
decodedMP3Answer += " -> File count: " + String(ansbuf[6], DEC);
break;
case 0x4C:
decodedMP3Answer += " -> Playing: " + String(ansbuf[6], DEC);
break;
case 0x4E:
decodedMP3Answer += " -> Folder file count: " + String(ansbuf[6], DEC);
break;
case 0x4F:
decodedMP3Answer += " -> Folder count: " + String(ansbuf[6], DEC);
break;
}
return decodedMP3Answer;
}
/********************************************************************************/
/*Function: Send command to the MP3 */
/*Parameter: byte command */
/*Parameter: byte dat1 parameter for the command */
/*Parameter: byte dat2 parameter for the command */
void sendCommand(byte command){
//theBugger(9, 9, 9, 9, "Unknown", "sendCommand");
sendCommand(command, 0, 0);
}
void sendCommand(byte command, byte dat1, byte dat2){
//theBugger(9, 9, 9, 9, "Unknown", "sendCommandAgain");
delay(20);
Send_buf[0] = 0x7E; //
Send_buf[1] = 0xFF; //
Send_buf[2] = 0x06; // Len
Send_buf[3] = command; //
Send_buf[4] = 0x01; // 0x00 NO, 0x01 feedback
Send_buf[5] = dat1; // datah
Send_buf[6] = dat2; // datal
Send_buf[7] = 0xEF; //
Serial.print("Sending: ");
for (uint8_t i = 0; i < 8; i++)
{
mp3.write(Send_buf[i]) ;
Serial.print(sbyte2hex(Send_buf[i]));
}
Serial.println();
}
/********************************************************************************/
/*Function: sbyte2hex. Returns a byte data in HEX format. */
/*Parameter:- uint8_t b. Byte to convert to HEX. */
/*Return: String */
String sbyte2hex(uint8_t b)
{
//theBugger(9, 9, 9, 9, "Unknown", "sbyte2hex");
String shex;
shex = "0X";
if (b < 16) shex += "0";
shex += String(b, HEX);
shex += " ";
return shex;
}
/********************************************************************************/
/*Function: shex2int. Returns a int from an HEX string. */
/*Parameter: s. char *s to convert to HEX. */
/*Parameter: n. char *s' length. */
/*Return: int */
int shex2int(char *s, int n){
//theBugger(9, 9, 9, 9, "Unknown", "shex2int");
int r = 0;
for (int i=0; i<n; i++){
if(s[i]>='0' && s[i]<='9'){
r *= 16;
r +=s[i]-'0';
}else if(s[i]>='A' && s[i]<='F'){
r *= 16;
r += (s[i] - 'A') + 10;
}
}
return r;
}
/********************************************************************************/
/*Function: sanswer. Returns a String answer from mp3 UART module. */
/*Parameter:- uint8_t b. void. */
/*Return: String. If the answer is well formated answer. */
String sanswer(void)
{
//theBugger(9, 9, 9, 9, "Unknown", "sanswer");
uint8_t i = 0;
String mp3answer = "";
// Get only 10 Bytes
while (mp3.available() && (i < 10))
{
uint8_t b = mp3.read();
ansbuf[i] = b;
i++;
mp3answer += sbyte2hex(b);
}
// if the answer format is correct.
if ((ansbuf[0] == 0x7E) && (ansbuf[9] == 0xEF))
{
return mp3answer;
}
return "???: " + mp3answer;
}
// ------------------- End MP3 Functions ---------------------------------------------
//--------------------------------- Start Admin Setup -------------------------------------------------
void adminSetup(){
//--------Code for selecting game mode------------------
gameExitCheck = 0;
teamRunDownClock = 3;
enableOvertime = 1;
limitGameLength = 1;
if (turnLEDOff == 0){
colorLEDChange( 0, 0, 0);
}
else{
colorLEDChange( 0, 255, 0);
}
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Select Game Mode", "Loading...", 2, 1, "list", gameModeSelection, gameModeSelectionSize);
}
else{
rotaryCombinedFunc ("Select Game Mode", "Loading...", 2, 1, "list", gameModeSelection, gameModeSelectionSize);
}
Serial.println(RotaryValue);
gameID = RotaryValue;
if (RotaryValue == 0){
gameSelectedMain = gameParametersArray[gameID][0];
//How do you want to interact with the button
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Buttn Intraction", "Loading...", 0, 1, "list", buttonInteractArray, buttonInteractArraySize);
}
else{
rotaryCombinedFunc ("Buttn Intraction", "Loading...", 0, 1, "list", buttonInteractArray, buttonInteractArraySize);
}
Serial.println("Button Interaction");
Serial.println(RotaryValue);
buttonInteraction = RotaryValue;
//0 = Tap
//1 = Hold X
//2 = Continuous
if ((buttonInteraction == 2)
)
{buttonMode = "Continuous";
}
else
{
buttonMode = "Tap";
}
//Victory condition
if(buttonInteraction == 2){
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Objective", "Loading...", 0, 1, "list", objectiveArray, 2);
}
else{
rotaryCombinedFunc ("Objective", "Loading...", 0, 1, "list", objectiveArray, 2);
}
}
else{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Objective", "Loading...", 0, 1, "list", objectiveArray, objectiveArraySize);
}
else{
rotaryCombinedFunc ("Objective", "Loading...", 0, 1, "list", objectiveArray, objectiveArraySize);
}
}
Serial.println("Objective");
Serial.println(RotaryValue);
objective = RotaryValue;
//0 = Both Count down time
//1 = Both Count Up Time
//2 = Both Reset Run Down
//3 = One Pause other count down
//4 = One Reset other count down
if ((objective == 3) || (objective == 4)
)
{buttonMode = "Pause";
}
if ((objective == 2) ||
(objective == 4)
)
{
checkReset = "Yes";
}
else {
checkReset = "No";
}
//Which team is trying to run down the clock?
if ((objective == 3) ||
(objective == 4)
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Team Rndown Clck", "Loading...", 0, 1, "list", teamColorArray, teamColorArraySize);
}
else{
rotaryCombinedFunc ("Team Rndown Clck", "Loading...", 0, 1, "list", teamColorArray, teamColorArraySize);
}
Serial.println("Team Run Down Clock");
Serial.println(RotaryValue);
teamRunDownClock = RotaryValue;
//0 = Red
//1 = Blue
}
// Select the objective time
if ((objective != 1)
)
{ timeDirection = "Down";
if ((teamRunDownClock != 0)
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Blue Objctv Time", "Loading...", 0, 1, "time", gameModeSelection, gameModeSelectionSize);
}
else{
rotaryCombinedFunc ("Blue Objctv Time", "Loading...", 180, 1, "time", gameModeSelection, gameModeSelectionSize);
}
Serial.println("Objective Time");
Serial.println(RotaryValue);
objectiveTimeBlue = RotaryValue;
objectiveTimeRed = RotaryValue;
checkTeamTime = 1;
}
}
else
{
timeDirection = "Up";
objectiveTimeBlue = 0;
objectiveTimeRed = 0;
}
// Are the team times different
if ((objective == 0) ||
(objective == 2)
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Is Red Time Diff", "Loading...", 1, 1, "list", YesNoArray, YesNoArraySize);
}
else{
rotaryCombinedFunc ("Is Red Time Diff", "Loading...", 1, 1, "list", YesNoArray, YesNoArraySize);
}
Serial.println("Are team times different?");
Serial.println(RotaryValue);
checkTeamTime = RotaryValue;
//0 = Yes
//1 = No
}
// Select the objective time
if ((objective != 1)
)
{
if ((teamRunDownClock == 0) ||
(checkTeamTime == 0)
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Red Objctv Time", "Loading...", 0, 1, "time", gameModeSelection, gameModeSelectionSize);
}
else{
rotaryCombinedFunc ("Red Objctv Time", "Loading...", 180, 1, "time", gameModeSelection, gameModeSelectionSize);
}
Serial.println("Objective Time");
Serial.println(RotaryValue);
objectiveTimeRed = RotaryValue;
}
}
// Set hold button x amount of time
if ((buttonInteraction == 1)
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Hld Bttn X 2CTRL", "Loading...", 0, 1, "time_ms", gameModeSelection, gameModeSelectionSize);
}
else{
rotaryCombinedFunc ("Hld Bttn X 2CTRL", "Loading...", 10, 1, "time_ms", gameModeSelection, gameModeSelectionSize);
}
Serial.println("Hold Button X amount of time");
Serial.println(RotaryValue);
holdXTime = RotaryValue;
if (holdXTime == 0){
variableX = "No";
}
else{
variableX = "X";
xLengthMillis = holdXTime*100L;
}
}
if ((objective == 0)
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Limit Gamelength", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
else{
rotaryCombinedFunc ("Limit Gamelength", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
Serial.println("Limit Gamelength?");
Serial.println(RotaryValue);
limitGameLength = RotaryValue;
//0 = Yes
//1 = No
}
// Set the overall game length
if ((objective == 1) ||
(objective == 3) ||
(objective == 4) ||
(limitGameLength == 0)
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Set Game Length", "Loading...", 0, 0, "time", gameModeSelection, gameModeSelectionSize);
}
else{
rotaryCombinedFunc ("Set Game Length", "Loading...", 300, 0, "time", gameModeSelection, gameModeSelectionSize);
}
Serial.println("Game Length Time");
Serial.println(RotaryValue);
gameLengthTime = RotaryValue;
limitGameLength = 0;
//variableCheck1 = gameLengthTime;
}
else{
gameLengthTime = 32000;
}
//If victory conditions 3&4
if ((objective == 3) ||
(objective == 4)
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Enable Overtime", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
else{
rotaryCombinedFunc ("Enable Overtime", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
Serial.println("Enable Overtime");
Serial.println(RotaryValue);
enableOvertime = RotaryValue;
//Enable Overtime
//0 = Yes
//1 = No
}
}
else if(RotaryValue > gameModeSelectionSize){
//error
inputLCDText = String(RotaryValue);
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
Serial.println("Error");
Serial.println(RotaryValue);
delay(3000);
}
// Preprogrammed
else{
Serial.println("You Selected ");
for (int i = 0; i < 7; i++) {
Serial.println(gameParametersArray[RotaryValue][i]);
}
//{name, buttonPush, timeX, timeLimit, timePause, timeReset, timeDirection}
gameSelectedMain = gameParametersArray[gameID][0];
buttonMode = gameParametersArray[gameID][1];
checkReset = gameParametersArray[gameID][5];
timeDirection = gameParametersArray[gameID][6];
// Select which team will be running down the clock
if ((gameSelectedMain == "Rogue One") ||
(gameSelectedMain == "Time Reset")
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Team Rndown Clck", "Loading...", 0, 1, "list", teamColorArray, teamColorArraySize);
}
else{
rotaryCombinedFunc ("Team Rndown Clck", "Loading...", 0, 1, "list", teamColorArray, teamColorArraySize);
}
Serial.println("Team Run Down Clock");
Serial.println(RotaryValue);
teamRunDownClock = RotaryValue;
Serial.println("Enable Overtime");
enableOvertime = 0;
Serial.println(enableOvertime);
}
// Select which team will use this timer to record tags
if ((gameSelectedMain == "Attrition") ||
(gameSelectedMain == "Death Clicks")
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Team Color", "Loading...", 0, 1, "list", teamColorArray, teamColorArraySize);
}
else{
rotaryCombinedFunc ("Team Color", "Loading...", 0, 1, "list", teamColorArray, teamColorArraySize);
}
Serial.println("Team Color");
Serial.println(RotaryValue);
teamRunDownClock = RotaryValue;
}
// Select which team will use this timer to record tags
if ((gameSelectedMain == "Attrition")
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("How many lives?", "Loading...", 0, 1, "int", teamColorArray, teamColorArraySize);
}
else{
rotaryCombinedFunc ("How many lives?", "Loading...", 15, 1, "int", teamColorArray, teamColorArraySize);
}
Serial.println("Attrition life Counter");
Serial.println(RotaryValue);
startLifeCount = RotaryValue;
redLifeCount = startLifeCount;
blueLifeCount = startLifeCount;
if(startLifeCount >15){
attritionLifeSoundModifier = 0;
}
else if(startLifeCount < 10){
if(startLifeCount > 5){
attritionLifeSoundModifier = 2;
}
else{
attritionLifeSoundModifier = 3;
}
}
else{
attritionLifeSoundModifier = 1;
}
}
// Select which team will use this timer to record tags
if ((gameSelectedMain == "Death Clicks")
)
{
Serial.println("Deathclicks life Counter");
startLifeCount = 0;
redLifeCount = startLifeCount;
blueLifeCount = startLifeCount;
Serial.println(startLifeCount);
}
// Select the objective time
if ((gameSelectedMain == "KoTH") ||
(gameSelectedMain == "Rogue One") ||
(gameSelectedMain == "Time Reset")
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Objective Time", "Loading...", 0, 1, "time", gameModeSelection, gameModeSelectionSize);
}
else{
rotaryCombinedFunc ("Objective Time", "Loading...", 180, 1, "time", gameModeSelection, gameModeSelectionSize);
}
Serial.println("Objective Time");
Serial.println(RotaryValue);
objectiveTimeBlue = RotaryValue;
objectiveTimeRed = RotaryValue;
}
else{
objectiveTimeBlue = 0;
objectiveTimeRed = 0;
}
// Set hold button x amount of time
if ((gameParametersArray[gameID][2] == "X")
)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Hld Bttn X 2CTRL", "Loading...", 0, 1, "time_ms", gameModeSelection, gameModeSelectionSize);
}
else{
rotaryCombinedFunc ("Hld Bttn X 2CTRL", "Loading...", 10, 1, "time_ms", gameModeSelection, gameModeSelectionSize);
}
Serial.println("Hold Button X amount of time");
Serial.println(RotaryValue);
holdXTime = RotaryValue;
if (holdXTime == 0){
variableX = "No";
}
else{
variableX = "X";
xLengthMillis = holdXTime*100L;
}
}
// Set the overall game length
if ((gameSelectedMain == "Time Keeper") ||
(gameSelectedMain == "Rogue One") ||
(gameSelectedMain == "Death Clicks") ||
(gameSelectedMain == "Domination") ||
(gameSelectedMain == "Hold The Hill") ||
(gameSelectedMain == "Time Reset")
)
{
if (gameSelectedMain == "Death Clicks"){
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Limit Gamelength", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
else{
rotaryCombinedFunc ("Limit Gamelength", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
Serial.println("Limit Gamelength?");
Serial.println(RotaryValue);
limitGameLength = RotaryValue;
//0 = Yes
//1 = No
if(limitGameLength == 0){
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Set Game Length", "Loading...", 0, 0, "time", gameModeSelection, gameModeSelectionSize);
}
else{
rotaryCombinedFunc ("Set Game Length", "Loading...", 300, 0, "time", gameModeSelection, gameModeSelectionSize);
}
Serial.println("Game Length Time");
Serial.println(RotaryValue);
gameLengthTime = RotaryValue;
//variableCheck2 = gameLengthTime;
}
else{
gameLengthTime = 32000;
}
}
else{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Set Game Length", "Loading...", 0, 0, "time", gameModeSelection, gameModeSelectionSize);
}
else{
rotaryCombinedFunc ("Set Game Length", "Loading...", 300, 0, "time", gameModeSelection, gameModeSelectionSize);
}
Serial.println("Game Length Time");
Serial.println(RotaryValue);
gameLengthTime = RotaryValue;
limitGameLength = 0;
//variableCheck2 = gameLengthTime;
}
}
else{
gameLengthTime = 32000;
}
}
// Use Audio to start game
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Use Start Audio", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
else{
rotaryCombinedFunc ("Use Start Audio", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
Serial.println("Use Start Audio");
Serial.println(RotaryValue);
startAudio = RotaryValue;
// Use end game count down
if (limitGameLength == 0)
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Use End Countdwn", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
else{
rotaryCombinedFunc ("Use End Countdwn", "Loading...", 0, 1, "list", YesNoArray, YesNoArraySize);
}
Serial.println("Use End Countdown");
Serial.println(RotaryValue);
endAudio = RotaryValue;
}
// Set start delay
if ((limitGameLength == 0) || (startAudio == 0))
{
if (enableRotaryEncoder == 1){
buttonCombinedFunc ("Set Start Delay", "Loading...", 0, 1, "time", gameModeSelection, gameModeSelectionSize);
}
else{
rotaryCombinedFunc ("Set Start Delay", "Loading...", 0, 1, "time", gameModeSelection, gameModeSelectionSize);
}
Serial.println("Start Delay Time");
startDelayTimeMillis = RotaryValue*1000L;
Serial.println(startDelayTimeMillis);
}
// check point
if (teamRunDownClock == 0){
runDownTeamColor = "Red";
objectiveTimeBlue = 32000;
}
else if (teamRunDownClock == 1){
runDownTeamColor = "Blue";
objectiveTimeRed = 32000;
}
Serial.println("Check1 Length");
Serial.println(gameLengthTime);
gameLengthMillis = gameLengthTime*1000L;
Serial.println("Check2 Length");
Serial.println(gameLengthTime);
Serial.println(gameLengthMillis);
timeOutput.mBlue = FuncCalcDigits (objectiveTimeBlue, 0);
timeOutput.kBlue = FuncCalcDigits (objectiveTimeBlue, 1);
timeOutput.jBlue = FuncCalcDigits (objectiveTimeBlue, 2);
timeOutput.iBlue = FuncCalcDigits (objectiveTimeBlue, 3);
timeOutput.mRed = FuncCalcDigits (objectiveTimeRed, 0);
timeOutput.kRed = FuncCalcDigits (objectiveTimeRed, 1);
timeOutput.jRed = FuncCalcDigits (objectiveTimeRed, 2);
timeOutput.iRed = FuncCalcDigits (objectiveTimeRed, 3);
timeOutput.mLimit = FuncCalcDigits (gameLengthTime, 0);
timeOutput.kLimit = FuncCalcDigits (gameLengthTime, 1);
timeOutput.jLimit = FuncCalcDigits (gameLengthTime, 2);
timeOutput.iLimit = FuncCalcDigits (gameLengthTime, 3);
teamTime = timeOutput;
// Starting parameters
gameTimeOver = "No";
teamInControl = "Green";
//playGameStart = "Yes";
//playGameEnd = "Yes";
attritionLifeIndex = 3 - attritionLifeSoundModifier;
attritionLifeSound = 33 - attritionLifeSoundModifier;
overTime = "No";
overTimeStart = "Yes";
alarmCheck = "Yes";
Serial.println("X Time");
Serial.println(xLengthMillis);
if(variableX == "X")
{
checkX = "No";
}
else
{
checkX = "Yes";
}
if(timeDirection == "Down"){
timeCheck_1 = timeCheck_1Down;
timeCheck_2 = timeCheck_2Down;
timeReset_1 = timeReset_1Down;
timeReset_2 = timeReset_2Down;
directionInput = directionDown;
}
else{
timeCheck_1 = timeCheck_1Up;
timeCheck_2 = timeCheck_2Up;
timeReset_1 = timeReset_1Up;
timeReset_2 = timeReset_2Up;
directionInput = directionUp;
}
//--------END Code for selecting game mode------------------
if (limitGameLength == 1)
{
displayLCD (0, 0, "Game Length" , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
displayLCD (0, 1, "not set" , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
delay(delayLCD);
}
else if ((gameSelectedMain == "Attrition") || (gameSelectedMain == "Death Clicks")){
}
else{
displayLCD (0, 0, "GameLengthLimit", "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
inputLCDText = String(timeOutput.mLimit) + String(timeOutput.kLimit) + ":" + String(timeOutput.jLimit) + String(timeOutput.iLimit);
displayLCD (0, 1, inputLCDText , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
delay(delayLCD);
}
}
//--------------------------------- End Admin Setup ------------------------------------------------------
int rotaryCombinedFunc (String LCDQuestion, String LCDResponse, int RotaryStart, int turnMultiplier, String typeOut, String listArray[], int sizeArray){
displayLCD (0, 0, LCDQuestion , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
RotaryPosition= RotaryStart; // To store Stepper Motor Position
PrevPosition = RotaryPosition - 1; // Save previous position in variable
if (typeOut == "int") {
inputLCDText = String(RotaryPosition);
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
Serial.println(RotaryPosition);
}
// Cycles through a list
else if (typeOut == "list") {
inputLCDText = listArray[RotaryPosition];
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
Serial.println(listArray[RotaryPosition]);
}
else if (typeOut == "time") {
funcTimeCalc (RotaryPosition);
}
while (2>1){
rotaryTurnFunc(RotaryStart, turnMultiplier, typeOut, listArray, sizeArray);
byte exitCheck = funcEncoderButton(LCDResponse);
if (exitCheck == 1){
break;
}
}
}
int rotaryTurnFunc(int RotaryStart, int turnMultiplier,String typeOut, String listArray[], int sizeArray){ // typeOut is int, list, or time
// Runs if rotation was detected
if (PrevPosition != RotaryPosition) {
PrevPosition = RotaryPosition; // Save previous position in variable
/*
if (rotationdirection) {
RotaryPosition=RotaryPosition+turnMultiplier;} // decrease Position by turnMultiplier
else {
RotaryPosition=RotaryPosition-turnMultiplier;} // increase Position by turnMultiplier
*/
//Changes the integer value on the LCD screen
if (typeOut == "int") {
if((RotaryPosition < 0)) {
RotaryPosition = 0;
}
inputLCDText = String(RotaryPosition);
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
Serial.println(RotaryPosition);
}
// Cycles through a list
else if (typeOut == "list") {
if((RotaryPosition> (sizeArray - 1))) {
RotaryPosition = 0;
} else if((RotaryPosition < 0)) {
RotaryPosition = sizeArray - 1;
}
inputLCDText = listArray[RotaryPosition];
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
Serial.println(listArray[RotaryPosition]);
PrevPosition = RotaryPosition;
}
else if (typeOut == "time") {
if((RotaryPosition < 0)) {
RotaryPosition = 0;
}
funcTimeCalc (RotaryPosition);
}
else if (typeOut == "time_ms") {
if((RotaryPosition < 0)) {
RotaryPosition = 599;
}
else if((RotaryPosition > 599)) {
RotaryPosition = 0;
}
funcTimeCalcMilli (RotaryPosition);
}
//TurnDetected = false; // do NOT repeat IF loop until new rotation detected
return RotaryPosition;
RotaryValue = RotaryPosition;
}
RotaryValue = RotaryPosition;
}
//----------------------- Start Rotary Button --------------------------------------------------------------------
byte funcEncoderButton(String LCDResponse){
byte check = 0;
if ((digitalRead(EncoderButton) == LOW)) {
startMillis = millis();
while ((digitalRead(EncoderButton) == LOW)) {
if ((millis()-startMillis) > 250) { // check if button was already pressed
check = 1;
displayLCD (0, 0, LCDResponse , "First"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
Serial.println("Button Pushed");
delay(1000);
break;
}
}
}
return check;
}
//----------------------- End Rotary Button -----------------------------------------------------------
// ----------------------Start Calculate Time Functions ------------------------------------------------------
int funcTimeCalc (int timeTotal) {
int fmR = timeTotal % 600;
int fm = (timeTotal - fmR)/ 600;
int fkR = fmR % 60;
int fk = (fmR - fkR)/ 60;
int fjR = fkR % 10;
int fj = (fkR - fjR)/ 10;
int fi = fjR;
clockDisplay(fm, fk, fj, fi,1);
}
int funcTimeCalcMilli (int timeTotal) {
int fmR = timeTotal % 100;
int fm = (timeTotal - fmR)/ 100;
int fkR = fmR % 10;
int fk = (fmR - fkR)/ 10;
int fj = fkR;
Serial.print(fm); // Left digit
Serial.print(fk); // Middle left digit
Serial.print("."); // turn on the colon
Serial.println(fj); // Middle right digit
inputLCDText = String(fm) + String(fk) + "." + String(fj) + " seconds";
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
}
int clockDisplay(int m, int k, int j, int i,int direction){
//int Clock_show = (m*1000+k*100+j*10+i)*direction;
//matrix.print(Clock_show, DEC);
//matrix.drawColon(true);
//matrix.writeDisplay();
Serial.print(m*direction); // Left digit
Serial.print(k*direction); // Middle left digit
Serial.print(":"); // turn on the colon
Serial.print(j*direction); // Middle right digit
Serial.println(i*direction); // Right digit
inputLCDText = String(m*direction) + String(k*direction) + ":" + String(j*direction) + String(i*direction);
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
}
// --------------------- End Calculate Time Functions -------------------------------------
//New Encoder
void read_encoder() {
// Encoder interrupt routine for both pins. Updates counter
// if they are valid and have rotated a full indent
//Serial.println("Check 2");
static uint8_t old_AB = 3; // Lookup table index
static int8_t encval = 0; // Encoder value
static const int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; // Lookup table
old_AB <<=2; // Remember previous state
if (digitalRead(ENC_A)) old_AB |= 0x02; // Add current state of pin A
if (digitalRead(ENC_B)) old_AB |= 0x01; // Add current state of pin B
encval += enc_states[( old_AB & 0x0f )];
// Update counter if encoder has rotated a full indent, that is at least 4 steps
if( encval > 3 ) { // Four steps forward
int changevalue = 1;
if((micros() - _lastIncReadTime) < _pauseLength) {
changevalue = _fastIncrement * changevalue;
}
_lastIncReadTime = micros();
RotaryPosition = RotaryPosition + changevalue; // Update counter
encval = 0;
}
else if( encval < -3 ) { // Four steps backward
int changevalue = -1;
if((micros() - _lastDecReadTime) < _pauseLength) {
changevalue = _fastIncrement * changevalue;
}
_lastDecReadTime = micros();
RotaryPosition = RotaryPosition + changevalue; // Update counter
encval = 0;
}
}
// ---------------------End Rotary Encoder Functions ---------------------------------------
// --------------------- Two Button's Admin Interface --------------------------------------
int buttonCombinedFunc (String LCDQuestion, String LCDResponse, int RotaryStart, int turnMultiplier, String typeOut, String listArray[], int sizeArray){
displayLCD (0, 0, LCDQuestion , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
RotaryPosition= RotaryStart; // To store Stepper Motor Position
PrevPosition = RotaryPosition - 1; // Save previous position in variable
if (typeOut == "int") {
inputLCDText = String(RotaryPosition);
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
Serial.println(RotaryPosition);
}
// Cycles through a list
else if (typeOut == "list") {
inputLCDText = listArray[RotaryPosition];
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
Serial.println(listArray[RotaryPosition]);
}
else if (typeOut == "time") {
funcTimeCalc (RotaryPosition);
}
while (2>1){
buttonTurnFunc(RotaryStart, turnMultiplier, typeOut, listArray, sizeArray);
if ((digitalRead(buttonBluepin) == LOW) || (timeExit == 1)){
timeExit = 0;
delay(250);
Serial.print(" Check 2 Final timeTotal ");
Serial.println(RotaryValue);
break;
}
}
}
int buttonTurnFunc(int RotaryStart, int turnMultiplier,String typeOut, String listArray[], int sizeArray){ // typeOut is int, list, or time
// Runs if rotation was detected
if (digitalRead(buttonRedpin) == LOW){
RotaryPosition = RotaryPosition + turnMultiplier;
delay(150);
}
if (PrevPosition != RotaryPosition) {
PrevPosition = RotaryPosition; // Save previous position in variable
/*
if (rotationdirection) {
RotaryPosition=RotaryPosition+turnMultiplier;} // decrease Position by turnMultiplier
else {
RotaryPosition=RotaryPosition-turnMultiplier;} // increase Position by turnMultiplier
*/
//Changes the integer value on the LCD screen
if (typeOut == "int") {
if((RotaryPosition < 0)) {
RotaryPosition = 0;
}
inputLCDText = String(RotaryPosition);
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
Serial.println(RotaryPosition);
}
// Cycles through a list
else if (typeOut == "list") {
if((RotaryPosition> (sizeArray - 1))) {
RotaryPosition = 0;
} else if((RotaryPosition < 0)) {
RotaryPosition = sizeArray - 1;
}
inputLCDText = listArray[RotaryPosition];
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
Serial.println(listArray[RotaryPosition]);
PrevPosition = RotaryPosition;
}
else if (typeOut == "time") {
if((RotaryPosition < 0)) {
RotaryPosition = 0;
}
RotaryPosition = buttonfuncTimeCalc (RotaryPosition);
RotaryValue = RotaryPosition;
Serial.print(" Check Final timeTotal ");
Serial.println(RotaryValue);
}
else if (typeOut == "time_ms") {
if((RotaryPosition < 0)) {
RotaryPosition = 0;
}
else if((RotaryPosition > 599)) {
RotaryPosition = 0;
}
RotaryPosition = buttonfuncTimeCalcMilli (RotaryPosition);
RotaryValue = RotaryPosition;
}
//TurnDetected = false; // do NOT repeat IF loop until new rotation detected
return RotaryPosition;
RotaryValue = RotaryPosition;
}
RotaryValue = RotaryPosition;
}
int buttonfuncTimeCalc (int timeTotal) {
byte digit = 0;
int digitValue = 0;
int digitValueAdd = 0;
byte skip = 0;
int fmR = timeTotal % 600;
int fm = (timeTotal - fmR)/ 600;
int fkR = fmR % 60;
int fk = (fmR - fkR)/ 60;
int fjR = fkR % 10;
int fj = (fkR - fjR)/ 10;
int fi = fjR;
clockDisplay(fm, fk, fj, fi,1);
while (digit < 4) {
byte skip = 0;
while (digit < 4) {
if (digitalRead(buttonBluepin) == LOW){
delay(250);
digit = digit + 1;
digitValueAdd = 0;
digitValue = 0;
skip = 1;
break;
}
if (digitalRead(buttonRedpin) == LOW){
delay(250);
digitValue = digitValue + 1;
Serial.print("digitValue ");
Serial.println(digitValue);
break;
}
}
if(skip == 0){
if (digitValue > 9){
if(digit == 0){
digitValueAdd = -9*600;
digitValue = 0;
}
else if(digit == 1){
digitValueAdd = -9*60;
digitValue = 0;
}
else if(digit == 3){
digitValueAdd = -9;
digitValue = 0;
}
}
else {
if(digit == 0){
digitValueAdd = 600;
}
else if(digit == 1){
digitValueAdd = 60;
}
else if(digit == 2){
if (digitValue > 5){
digitValueAdd = -50;
digitValue = 0;
}
else {
digitValueAdd = 10;
}
}
else if(digit == 3){
digitValueAdd = 1;
}
}
timeTotal = timeTotal + digitValueAdd;
Serial.print("timeTotal ");
Serial.println(timeTotal);
fmR = timeTotal % 600;
fm = (timeTotal - fmR)/ 600;
fkR = fmR % 60;
fk = (fmR - fkR)/ 60;
fjR = fkR % 10;
fj = (fkR - fjR)/ 10;
fi = fjR;
clockDisplay(fm, fk, fj, fi,1);
}
}
timeExit = 1;
Serial.print(" Final timeTotal ");
Serial.println(timeTotal);
return timeTotal;
RotaryValue = timeTotal;
}
int buttonfuncTimeCalcMilli (int timeTotal) {
byte digit = 0;
int digitValue = 0;
int digitValueAdd = 0;
int fmR = timeTotal % 100;
int fm = (timeTotal - fmR)/ 100;
int fkR = fmR % 10;
int fk = (fmR - fkR)/ 10;
int fj = fkR;
Serial.print(fm); // Left digit
Serial.print(fk); // Middle left digit
Serial.print("."); // turn on the colon
Serial.println(fj); // Middle right digit
inputLCDText = String(fm) + String(fk) + "." + String(fj) + " seconds";
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
while (digit < 4) {
while (digit < 4) {
if (digitalRead(buttonBluepin) == LOW){
delay(250);
digit = 5;
break;
}
if (digitalRead(buttonRedpin) == LOW){
delay(250);
timeTotal = timeTotal + 1;
break;
}
}
Serial.print("timeTotal ");
Serial.println(timeTotal);
fmR = timeTotal % 100;
fm = (timeTotal - fmR)/ 100;
fkR = fmR % 10;
fk = (fmR - fkR)/ 10;
fj = fkR;
inputLCDText = String(fm) + String(fk) + "." + String(fj) + " seconds";
displayLCD (0, 1, inputLCDText , "Second"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
}
timeExit = 1;
Serial.print(" Final timeTotal ");
Serial.println(timeTotal);
RotaryValue = timeTotal;
return timeTotal;
}
// Calculate time
byte FuncCalcDigits (int timeTotal, byte digitPlace) {
byte digitPlaceArray[] = {9,9,9,9};
int fmR = timeTotal % 600;
digitPlaceArray[0] = (timeTotal - fmR)/ 600;
int fkR = fmR % 60;
digitPlaceArray[1] = (fmR - fkR)/ 60;
int fjR = fkR % 10;
digitPlaceArray[2] = (fkR - fjR)/ 10;
digitPlaceArray[3] = fjR;
return digitPlaceArray[digitPlace];
}
void USBCheck (){
int BlueHitStart = 1;
displayLCD (0, 0, "USB plugged in?", "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
displayLCD (0, 1, "Power switch on?" , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
while(BlueHitStart < 2){
if (digitalRead(buttonRedpin) == LOW)
{
displayLCD (0, 0, "Plug in the USB" , "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
displayLCD (0, 1, "Turn power on" , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
delay(delayLCD); // add a delay to allow time for the button to be released
displayLCD (0, 0, "USB plugged in?", "Both"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
displayLCD (0, 1, "Power switch on?" , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
delay(250); // add a delay to allow time for the button to be released
}
if (digitalRead(buttonBluepin) == LOW) //when red LED is off and red button is pushed
{
BlueHitStart = BlueHitStart + 1; //incrementally increase the variable to track which digit to edit
colorLEDChange( 0, 255, 0);
delay(250); // add a delay to allow time for the button to be released
}
}
}
void parameterCheck(){
Serial.print("gameID ");
Serial.println(gameID);
Serial.print("Button Interaction ");
Serial.println(buttonInteraction);
Serial.print("Objective ");
Serial.println(objective);
Serial.print("checkReset ");
Serial.println(checkReset);
Serial.print("Team Run Down Clock ");
Serial.println(teamRunDownClock);
Serial.print("timeDirection ");
Serial.println(timeDirection);
Serial.print("Are team times different? ");
Serial.println(checkTeamTime);
Serial.print("Objective Time Blue ");
Serial.println(objectiveTimeBlue);
Serial.print("Objective Time Red ");
Serial.println(objectiveTimeRed);
Serial.print("Hold Button X amount of time ");
Serial.println(holdXTime);
Serial.print("variableX ");
Serial.println(variableX);
Serial.print("xLengthMillis ");
Serial.println(xLengthMillis);
Serial.print("Limit Gamelength? ");
Serial.println(limitGameLength);
Serial.print("Game Length Time ");
Serial.println(gameLengthTime);
Serial.print("gameLengthMillis ");
Serial.println(gameLengthMillis);
Serial.print("Enable Overtime ");
Serial.println(enableOvertime);
Serial.print("gameSelectedMain ");
Serial.println(gameSelectedMain);
Serial.print("buttonMode ");
Serial.println(buttonMode);
Serial.print("Start Delay Time ");
Serial.println(startDelayTimeMillis);
Serial.print("Use Start Audio ");
Serial.println(startAudio);
Serial.print("Use End Countdown ");
Serial.println(endAudio);
Serial.print("Blue Time ");
Serial.print(timeOutput.mBlue);
Serial.print(timeOutput.kBlue);
Serial.print(":");
Serial.print(timeOutput.jBlue);
Serial.println(timeOutput.iBlue);
Serial.print("Red Time ");
Serial.print(timeOutput.mRed);
Serial.print(timeOutput.kRed);
Serial.print(":");
Serial.print(timeOutput.jRed);
Serial.println(timeOutput.iRed);
Serial.print("Limit Time ");
Serial.print(timeOutput.mLimit );
Serial.print(timeOutput.kLimit );
Serial.print(":");
Serial.print(timeOutput.jLimit );
Serial.println(timeOutput.iLimit );
Serial.print("gameTimeOver ");
Serial.println(gameTimeOver);
Serial.print("teamInControl ");
Serial.println(teamInControl);
//Serial.print("playGameStart ");
//Serial.println(playGameStart);
//Serial.print("playGameEnd ");
//Serial.println(playGameEnd);
Serial.print("attritionLifeIndex ");
Serial.println(attritionLifeIndex);
Serial.print("attritionLifeSound ");
Serial.println(attritionLifeSound);
Serial.print("overTime ");
Serial.println(overTime);
Serial.print("overTimeStart ");
Serial.println(overTimeStart);
Serial.print("alarmCheck ");
Serial.println(alarmCheck);
Serial.print("checkX ");
Serial.println(checkX);
Serial.print("timeCheck_1 ");
Serial.println(timeCheck_1);
Serial.print("timeCheck_2 ");
Serial.println(timeCheck_2);
Serial.print("timeReset_1 ");
Serial.println(timeReset_1);
Serial.print("timeReset_2 ");
Serial.println(timeReset_2);
Serial.print("directionInput ");
Serial.println(directionInput);
}
void gameLengthDisplay (){
if (limitGameLength == 0)
{
currentSecondMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started). This is used to check when to increment the 7 segment display.
gameCheckMillis = gameLengthMillis - (currentSecondMillis - gameStartMillis);
gameLengthTimeDisplay = gameCheckMillis/1000L;
if (gameLengthTimeDisplay > 0)
{
inputLCDText = String(FuncCalcDigits (gameLengthTimeDisplay, 0)) + String(FuncCalcDigits (gameLengthTimeDisplay, 1)) + ":" + String(FuncCalcDigits (gameLengthTimeDisplay, 2)) + String(FuncCalcDigits (gameLengthTimeDisplay, 3));
displayLCD (11, 1, inputLCDText , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
}
else{
displayLCD (11, 1, "00:00" , "None"); // displayLCD (int digit, int line, String lcdText, String "None"/"First"/"Second"/"Both")
}
}
}
Step 10: Testing/ Operating the Timer/
Admin Interface
I use the multimeter continuity function to verify there are no unintended connections.
​
Once your satisfied with your checks, plug in your USB power bank and test it out. The LCD screen will ask you a series of questions. Check out the videos on how to navigate the menu. Sorry for the blurry LCD screen.
​
Setup Videos: