//Assign joystick pins
const int xPin = A7;
const int yPin = A6;

// Assign button pins
const int aButtonPin = 7;
const int xButtonPin = 9;
const int yButtonPin = 11;

// Initiate default values
int xPosition = 0;
int yPosition = 0; 
int xMax = 0;
int xMin = 999;
int yMax = 0;
int yMin = 999;
int xMaxThreshold = 0;
int xMinThreshold = 0;
int yMaxThreshold = 0;
int yMinThreshold = 0;
int thresholdIncrementer = 5;
int thresholdAmmount = 35;
int aButtonState = 0;
int xButtonState = 0;
int yButtonState = 0;  
int stepNumber = 0;
bool messagePrinted = false;


void setup (void) {
  Serial.begin(9600); 
  pinMode(xPin, INPUT);
  pinMode(yPin, INPUT);
  pinMode(7, INPUT);
  pinMode(9, INPUT);
  pinMode(11, INPUT);
}

// Prints message to serial monitor once.
void printMessageOnce(String message1, String message2){
  if(!messagePrinted){
    Serial.flush();
    Serial.println("\n________________________\n");
    Serial.flush();
    Serial.println(message1);
    Serial.flush();
    Serial.println();
    Serial.flush();
    Serial.println(message2);
    Serial.flush();
    messagePrinted = true;
  }
}

// Inital step giving brief explanation.
void step0(void) {
  printMessageOnce("This code allows users to determine the best threshold values to use for converting joystick anolog values to digital button (dpad) presses.", "Press A to begin.");
}

// This step obtains and saves the maximum and minimum X and Y joystick values.
void step1 (void) {
  printMessageOnce("Rotate joystick 360° at the furthest position multiple times clockwise and counter-clockwise.\nReading joystick values...",
  "Press A (after rotating multiple times in both directions) to coninue.");
  xPosition = analogRead(xPin);
  if(xPosition > xMax){
    xMax = xPosition;
  }
  if(xPosition < xMin){
    xMin = xPosition;
  }
  
  yPosition = analogRead(yPin);
  if(yPosition > yMax){
    yMax = yPosition;
  }
  if(yPosition < yMin){
    yMin = yPosition;
  }
}



// This step prints the the maximum and minimum X and Y joystick values.
void step2(void){
  printMessageOnce(String("Maximum Y Position: ") + yMax + String("\nMinumum Y Position: ") + yMin + String("\n\nMaximum X Position: ") + xMax + String("\nMinumum X Position: ") + xMin, "Press A to continue.");
}

// This step assigns the maximum and minimum X and Y threshold values.
void step3(void){
  yMaxThreshold = yMax - thresholdAmmount;
  yMinThreshold = yMin + thresholdAmmount;
  xMaxThreshold = xMax - thresholdAmmount;
  xMinThreshold = xMin + thresholdAmmount;
  
  printMessageOnce(String("Threshold Ammount: ")+ thresholdAmmount + String("\n\nyMaxThreshold: ") + yMaxThreshold + String("\nyMinThreshold: ") + yMinThreshold + String("\n\nxMaxThreshold: ") + xMaxThreshold + String("\nxMinThreshold: ") + xMinThreshold, 
  "Press A to start testing this configuration.");
}

// This step prints the direction the joystick is moved as well as checks for X and Y button presses to increase or decrease the sensitivity (increases or decreases the threshold ammount).
void step4(void){
   printMessageOnce("Move joystick in any direction to test configuration.\nPress X button to decrease sensitivity or Y button to increase sensitivity.", "Press A once you are satisfied with the sensitivity.");

  xButtonState = digitalRead(xButtonPin);
  if(xButtonState == HIGH){
    thresholdAmmount -= thresholdIncrementer;
    Serial.println("Sensitivity decreased by 5.");
    stepNumber = 3;
    messagePrinted = false;
    delay(500);
  }
  yButtonState = digitalRead(yButtonPin);
  if(yButtonState == HIGH){
    thresholdAmmount += thresholdIncrementer;
    Serial.println("Sensitivity increased by 5.");
    stepNumber = 3;
    messagePrinted = false;
    delay(500);
  }
  
  xPosition = analogRead(xPin);
  if(xPosition > xMaxThreshold){
    Serial.println("Right");
    delay(500);
  }
  if(xPosition < xMinThreshold){
   Serial.println("Left");
   delay(500);
  }
  
  yPosition = analogRead(yPin);
  if(yPosition > yMaxThreshold){
    Serial.println("Up");
    delay(500);
  }
  if(yPosition < yMinThreshold){
   Serial.println("Down");
   delay(500);
  }
}

// This steps informs the user that all steps have been completed and prints the values to enter into the AMG_GT3_Wheel sketch.
void stepsCompleted(void){
  printMessageOnce("You have completed all steps for obtaining the proper configuration values.\nEnter the following values in the AMG_GT3_Wheel code:" ,String("\n const int yMaxThreshold = ") + yMaxThreshold + String(";\n const int yMinThreshold = ") + yMinThreshold + String(";\n\n const int xMaxThreshold = ") + yMaxThreshold + String(";\n const int xMinThreshold = ") + xMinThreshold + String(";"));
  Serial.println("\nYou may now exit this program.\n\nSerial communication terminated.");
  Serial.end();
}


// Main loop that checks if the A button is pressed tp move to the next step or B button pressed to start over.
void loop() {
  aButtonState = digitalRead(aButtonPin);

  switch(stepNumber) {
    case 0:
      step0();
      break;
    case 1:
      step1();
      break;
    case 2:
      step2();
      break;
    case 3:
      step3();
      break;
    case 4:
      step4();
      break;
    default:
      stepsCompleted();
      break;
  }

  if(aButtonState == HIGH){
    messagePrinted = false;
    stepNumber++;
    delay(500);
  }
}
