#include <Wire.h>
#include <Keypad.h>
#include <Adafruit_SSD1306.h>
#include <AccelStepper.h>

#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_ADDR 0x3C // OLED I2C address

Adafruit_SSD1306 display(OLED_WIDTH, OLED_HEIGHT);
#define dirPin 10 // Direction pin for the stepper motor.
#define stepPin 9 // Step pin for the stepper motor.
#define motorInterfaceType 1
#define beep 11 // Buzzer pin
#define buttonPin_up 12
#define buttonPin_down 13
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

volatile long CtaEnc = 0; // Position relative to the target (encoder count).
int Vmax = 255; // Maximum PWM value.
int Vmin = 20; // Minimum PWM value without stopping the motor.
int Vprom = 195; // Average speed.
int Fvel = 0; // Speed reduction factor.
int Steps = 0.000; // Number of steps to move.
int Repetitions = 1; // Number of times to repeat the movement.
int MotorDirection = 1; // Motor direction (1 for forward, -1 for backward).
int MotorSpeed = 100; // Motor speed percentage (0 to 100%).
int BlinkDelay = 500; // Delay for blinking effect.
int pot = 50;
int BladeThickness = 0;
int AddBlade = 1;  //1 for yes -1 no 
int TotalSteps = 0; // Combined steps from TotalSteps and Steps


byte col = 42; // Column for display.
const byte ROWS = 4;
const byte COLS = 4;

char keys[ROWS][COLS] = {
  {'1', '2', '3', 'a'},
  {'4', '5', '6', 'b'},
  {'7', '8', '9', 'c'},
  {'.', '0', '#', 'D'}
};

byte colPins[COLS] = {A3, A2, A1, A0}; // Column pins.
byte rowPins[ROWS] = {6, 5, 4, 3}; // Row pins.

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
char key;
boolean entryComplete;
boolean isSettingSteps = true; // Flag to switch between setting steps, repetitions, speed, and position.
boolean isSettingThick = false; // Flag to set repetitions.
boolean isSettingSpeed = false; // Flag to set speed.
boolean isSettingPos = false; // Flag to set position.
boolean startMotor = false; // Flag to start the motor.
boolean button = false;
unsigned long lastBlinkTime = 0; // For handling the blink effect.
boolean blinkState = false; // For controlling blinking.


void setup() {
  
  pinMode(buttonPin_up, INPUT);
  pinMode(buttonPin_down, INPUT);
  pinMode(beep, OUTPUT); // Initialize buzzer pin
  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(500);
  stepper.setSpeed(500);
  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.setTextSize(2); // Use smaller text size
  display.setTextColor(WHITE);
  display.clearDisplay();
  display.setCursor(10,0);
  display.print("Sliver Me Timbers");
  display.display();
  delay(2000);
}

void loop() {
  stepper.setMaxSpeed(1000);//reset the stepper speed after the execute steps runs    vvv
  stepper.setSpeed(1000);// otherwise our jog buttons kept the speed of execute steps ^^^
  updateDisplay();// Update the display with current values and blinking effect.
  
  buttonJog_up();
  buttonJog_down();
  readKeypad(); // Handle keypad input.
   readPot(); // updates the display live and changes the value of MotorSpeed with the readinng of the potentiometer
 // addSteps();


if (AddBlade > 0){
  TotalSteps = Steps + BladeThickness;
} else if (AddBlade < 0 ){
  TotalSteps = Steps; 
}
  





 if (startMotor) {
    executeSteps(); // Start motor only when flag is set.
    startMotor = false; // Reset the flag after starting the motor.
  }

  
}



void updateDisplay() {
    
  display.clearDisplay();
  display.setTextSize(1); // Use smaller text size
  unsigned long currentTime = millis();

  if (currentTime - lastBlinkTime >= BlinkDelay) {
    lastBlinkTime = currentTime;
    blinkState = !blinkState; // Toggle blink state.
  }
if (isSettingSteps) {
    display.setCursor(0, 0);
    display.print(blinkState ? "> Steps: " : "  Steps: ");
    display.print(Steps);
  } else {
    display.setCursor(0, 0);
    display.print("  Steps: ");
    display.print(Steps);
  }

  if (isSettingThick) {
    display.setCursor(0, 10);
    display.print(blinkState ? "> Kerf: " : "  Kerf: ");
    display.print(BladeThickness);
  } else {
    display.setCursor(0, 10);
    display.print("  Kerf: ");
    display.print(BladeThickness);
  }
 
  display.setCursor(0, 20);
  display.print("Speed: ");
  display.print(MotorSpeed);
  display.print("%");
  
  display.setCursor(0, 30);
  display.print("Direction: ");
  display.print(MotorDirection == 1 ? "UP" : "Down");

  display.setCursor(0, 40);
  display.print("Add Kerf?: ");
  display.print(AddBlade == 1 ? "Yes" : "No");

  display.setCursor (0,50);
  display.print("Position:");
  display.print(stepper.currentPosition());
  
  display.setCursor (80,50);
  display.print ("Value");
  display.print (TotalSteps);

  display.display();

}
 
void readKeypad() {
  key = keypad.getKey();

  if (key) {
    tone(beep, 4000, 10); // Sound buzzer when a key is pressed.

    if (isDigit(key)) {
      // Process numeric input based on the current mode.
      float digit = key - '0';
      if (isSettingSteps) {
        Steps = Steps * 10 + digit;
        
    } else if (isSettingThick) {
       BladeThickness = BladeThickness * 10 + digit;
     } else if (isSettingPos) {
        stepper.setCurrentPosition(stepper.currentPosition() + digit);
      }
    } else if (key == '#') {
      // Switch between Steps, Reps, Speed, and Position.
      if (isSettingSteps) {
        isSettingSteps = false;
      isSettingThick = true;
      } else if (isSettingThick) {
       isSettingThick = false;
        isSettingSteps = true;
      }
    } else if (key == 'D') {
      // Start motor when 'D' is pressed.
      startMotor = true;

    } else if (key == 'b') {
      // Add Blade Thickness
     AddBlade = -AddBlade;

    } else if (key == 'a') {
      // Toggle motor direction.
      MotorDirection = -MotorDirection;

    } else if (key == 'c') {
      // Handle delete function.
      if (isSettingSteps && Steps > 0) {
        Steps /= 10;
      }else if (isSettingThick && BladeThickness > 0) {
        BladeThickness /= 10;
      }
    }
  }
}



//Original code
void executeSteps() {
   
  for (int i = 0;i < Repetitions; i++) {
    stepper.setCurrentPosition(0);
    stepper.moveTo(TotalSteps * MotorDirection);
    while (stepper.distanceToGo() != 0) {
      stepper.run();
    }
 }
}

void readPot(){
int pot = analogRead(A6); // Read potentiometer value 0 to 1023
  MotorSpeed = map(pot , 0, 1023,0,100);
  stepper.setMaxSpeed(map(MotorSpeed, 0, 100, 0, 1000)); // Map motor speed percentage to actual speed value.
}

void buttonJog_up(){
 
 
   while (digitalRead(buttonPin_up) == HIGH) {
  int pot = analogRead(A6); // Read potentiometer value 0 to 1023
  MotorSpeed = map(pot , 0, 1023,0,100);
  button = digitalRead(buttonPin_up);
  stepper.setSpeed(map(MotorSpeed, 0, 100, 1, 1000)); // Map motor speed percentage to actual speed value.
  
   //stepper.setCurrentPosition(0);
   //stepper.moveTo(10000);
    
  stepper.runSpeed();
    

  }
}
void buttonJog_down(){
 
   while (digitalRead(buttonPin_down) == HIGH) {
  int pot = analogRead(A6); // Read potentiometer value 0 to 1023
  MotorSpeed = map(pot , 0, 1023,1,100);
  button = digitalRead(buttonPin_down);
  stepper.setSpeed(map(MotorSpeed, 0, 100, -1, -1000)); // Map motor speed percentage to actual speed value.
  
   stepper.runSpeed();
  }
}
A4988