// Squiduino Designed by Sagar Sapkota.
//A product of buildcircuit.com


 
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <TM1637Display.h>
#include <Servo.h>

//Changable parameters
#define BRIGHTNESS 5                      // Set the display brightness (0-7)
#define motion_tracking_time 15           //How much time(second) should sensor track after red light
int play_range[] = {800,6000};           // This is the time range to be chosen randomly between Green light and Red Light (in millisecond).
int timeOption[] = {60,120,180,240,300};  //in seconds
int lookFront_angle =  0;
int lookBack_angle = 180;

//Pin defination. Should not be touched
const int LED_red = A1;
const int LED_Green = A0;
const int LED_WHITE= A2;

const int start_switch = 10;
const int stop_switch = 9;
const int scroll_switch = 8;
const int rule_switch = 7;
const int buzzerPin = 13;
const int motionPin = 4;
const int CLK = 2;
const int DIO = 3;
const int servoPin = 11;


int position = 4;                     //0 to 4; total 5 selectable timeOption
int gameDuration = timeOption[position]; // selecting last one(5:00) as default countdown time
uint32_t startTime;                   //keep tract of full game time
uint32_t motion_tracking_start_time;  //for keeping time of how long to track movement
uint32_t round_start_time;            //each round start time
long randNumber;                      // for storing random number
bool isGreen = false;                 //default is RED, so false

Servo myServo;
SoftwareSerial mySerial(5, 6); // RX, TX



DFRobotDFPlayerMini myDFPlayer;
TM1637Display display = TM1637Display(CLK, DIO);

void setup() 
{
   
  
  myServo.attach(servoPin);
  //set random seed number
  randomSeed(analogRead(0));
  
  //3 push buttons with pullups
  pinMode(start_switch,INPUT_PULLUP);      //Define each button as input with pullup
  pinMode(stop_switch,INPUT_PULLUP);
  pinMode(scroll_switch,INPUT_PULLUP);
    pinMode(rule_switch,INPUT_PULLUP);
    
  pinMode(LED_red,OUTPUT);
  pinMode(LED_Green,OUTPUT);
  pinMode(buzzerPin,OUTPUT);
  pinMode(LED_WHITE,OUTPUT);
  
  pinMode(motionPin,INPUT);

  turnLED_off();
  
  display.setBrightness(BRIGHTNESS);
  display.clear();

  
  Serial.begin(9600);
  mySerial.begin(9600);                                      //Start communication with the DFplayer module

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    turnLED_yellow();//yellow light will indicates error
    while(true);
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(30);  //Set volume value. From 0 to 30
  
   delay(100);

  startTime = startGame(); //wait for starting the game(pressing Start button) or any posible game duration change(pressing scroll button)
                                    //will return startTime in millisecond
  
  delay(1000); //wait a second before we start
}


void(* resetFunc) (void) = 0;//declare reset function at address 0

void loop()
{
  
  updateTime(); //update time in each loop
  
  if(!isGreen)
  {
    myServo.write(lookBack_angle);//look back
    delay(700);
    playGreenLight(); //if not green then play green light
    round_start_time = millis(); //reset round start time
    randNumber = random(play_range[0],play_range[1]); // generate random green light duration for this round
    isGreen = true;
  }


  //if certain random time spent in green light; play red light and check movement
  if((millis()- round_start_time)>= randNumber && isGreen)
  {
    playRedLight();
    myServo.write(lookFront_angle); //look front
    delay(1000);
    isGreen = false; //set light state

    //check for movement using motion sensor
    motion_tracking_start_time = millis();
    
    playSensorScan_andEliminate();//will scan for motion_tracking_time duration, whoever moves in between this time gets eliminated 
  }
  
  
  if(stop_press())
    {
        Serial.println("resetting");
        resetFunc();  //call reset
        delay(100);
    }

}//end of void loop
