//------------------------------- librarys ----------------------------------

#include <LiquidCrystal.h>
#include <Servo.h>
 
//------------------------------- lcd ----------------------------------
LiquidCrystal lcd(12, 11, 2, 3, 4, 5);
 
//------------------------------- stepper ----------------------------------
#define stepPin 7
#define dirPin 8
 
//------------------------------- servo ----------------------------------
Servo snippers;
#define servo 10
#define openAngle 180
#define closedAngle 0
 
//------------------------------- input ----------------------------------
 
#define leftButton 14
#define rightButton 9
#define upButton 15
#define downButton 6
 
//------------------------------- user settings ----------------------------------
unsigned int wireLength = 10;
unsigned int wireQuantity = 24;
 
//------------------------------- system settings ----------------------------------
int state = 0;
int incrementSpeed = 1;
int previousWireLength = 0;
int previousWireQuantity = 0;
float mmPerStep = 0.0096;
 
 
void setup() {
  Serial.begin(9600);
 
 
  lcd.begin(16, 2); //LCD columns and rows
 
 
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(leftButton, INPUT_PULLUP);
  pinMode(rightButton, INPUT_PULLUP);
 
  pinMode(stepPin,OUTPUT);
  pinMode(dirPin,OUTPUT);
 
  snippers.attach(servo);
 
  snippers.write(openAngle);
   
  delay(1000);
}
 
void loop() {
  if (!digitalRead(rightButton)){
    if(state == 5){
      state = 0;
    }
    else{
      state += 1;
    }
    delay(200);
    lcd.clear();
  }
  if (!digitalRead(leftButton) && state > 0 && state < 4){
    state -=1;
    delay(200);
    lcd.clear();
  }
 
 
  switch (state){
    case 0:
      homeScreen();
      break;
    case 1:
       chooseWireLength();
       break;
    case 2:
      chooseWireQuantity();
      break;
    case 3:
      confirm();
      break;
    case 4:
      currentlyCutting();
      break;
    case 5:
      finishedCutting();
      break;
  }
 
}
 
 
void homeScreen(){
  lcd.setCursor(0, 0);
  lcd.print("WIRE CUTTER");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}
 
 
void chooseWireLength(){
  wireLength = changeValue(wireLength);
 
  //clear LCD if required
  if(previousWireLength != wireLength){
    lcd.clear();
    previousWireLength = wireLength;
  }
 
  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("LENGTH:" + (String)wireLength + "cm");
  displayNavigation();
}
 
void chooseWireQuantity(){
  wireQuantity = changeValue(wireQuantity);
 
  //clear LCD if required
  if(previousWireQuantity != wireQuantity){
    lcd.clear();
    previousWireQuantity = wireQuantity;
  }
 
  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("QUANTITY:" + (String)wireQuantity);
  displayNavigation();
}
 
void confirm(){
  lcd.setCursor(0, 0);
  lcd.print((String)wireLength + "Cm x " + (String)wireQuantity + "pcs");
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(10, 1);
  lcd.print("START>");
  delay(100);
}
 
void currentlyCutting(){
  lcd.setCursor(0, 0);
  lcd.print((String)0 + "/" + (String)wireQuantity);
  lcd.setCursor(0, 1);
  lcd.print("???s");
  int stepsToTake = (int)wireLength/mmPerStep;
  for(int i = 0; i < wireQuantity; i++){
    unsigned long timeForOneCycle = millis();
    digitalWrite(dirPin,HIGH);
    for(int x = 0; x < stepsToTake; x++) {
      digitalWrite(stepPin,HIGH);
      delayMicroseconds(500);
      digitalWrite(stepPin,LOW);
      delayMicroseconds(500);
    }
   
    lcd.setCursor(0, 0);
    lcd.print((String)(i+1) + "/" + (String)wireQuantity);
   
    snippers.write(closedAngle);
    delay(1000);
    snippers.write(openAngle);
    delay(1000);
 
   
    lcd.setCursor(0, 1);
 
    unsigned long timeRemaining = ((millis() - timeForOneCycle)*(wireQuantity - (i+1)))/1000;
    lcd.print((String)timeRemaining + "s    ");
   
  }
  wireLength = 0;
  wireQuantity = 0;
  state = 5;
}
 
void finishedCutting(){
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("CUTTING COMPLETE");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}
 
 
int changeValue(int currentValue){
  if (!digitalRead(upButton)) {
    delay(100);
    currentValue += incrementSpeed;
    
  }
  if (!digitalRead(downButton)) {
    if(currentValue - incrementSpeed >= 0){
      delay(100);
      currentValue -= incrementSpeed;
    
    }
    else{
      currentValue = 0;
    }
  }
  if (!digitalRead(downButton) && !digitalRead(upButton)){
    incrementSpeed = 1;
  }
  return currentValue;
}
 
void displayNavigation(){
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}
nano:12
nano:11
nano:10
nano:9
nano:8
nano:7
nano:6
nano:5
nano:4
nano:3
nano:2
nano:GND.2
nano:RESET.2
nano:0
nano:1
nano:13
nano:3.3V
nano:AREF
nano:A0
nano:A1
nano:A2
nano:A3
nano:A4
nano:A5
nano:A6
nano:A7
nano:5V
nano:RESET
nano:GND.1
nano:VIN
nano:12.2
nano:5V.2
nano:13.2
nano:11.2
nano:RESET.3
nano:GND.3
lcd1:VSS
lcd1:VDD
lcd1:V0
lcd1:RS
lcd1:RW
lcd1:E
lcd1:D0
lcd1:D1
lcd1:D2
lcd1:D3
lcd1:D4
lcd1:D5
lcd1:D6
lcd1:D7
lcd1:A
lcd1:K
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
btn3:1.l
btn3:2.l
btn3:1.r
btn3:2.r
btn4:1.l
btn4:2.l
btn4:1.r
btn4:2.r
A4988
drv1:ENABLE
drv1:MS1
drv1:MS2
drv1:MS3
drv1:RESET
drv1:SLEEP
drv1:STEP
drv1:DIR
drv1:GND.1
drv1:VDD
drv1:1B
drv1:1A
drv1:2A
drv1:2B
drv1:GND.2
drv1:VMOT
stepper1:A-
stepper1:A+
stepper1:B+
stepper1:B-
servo1:GND
servo1:V+
servo1:PWM