#include <AccelStepper.h>
#include <Arduino.h>
#include <Wire.h>

// ================================================================================================================
// *********************           Change this setting to adjust clock      V1.0 18/11/2025   *********************

//                     The test code simulates 1 & 60 minutes and 12 hours of the clock .
//           This is to ensure the step value for the stepper motor is correct, or as close as possible.
//              The stepper motor is 32 steps per revolution, has an internal gearbox, nominally 1:64
//                 however it is actually  1:63.68  so not perfectly 2048 steps per revolution.
//
//
//                             The code will allow you to set the clock to 12:00.
//            Then Put a witness mark (use a small piece of masking tape) at the bottom of the minute dial
//             near the number 8. Use a folded biece of card under the clock to make another witness mark
//                                 and align the two marks, by moving the card.
//
//        At each 10 minute, hour and 12 hours time, the marks should be perfectly aligned, if not
//             if the clock is slow (mark on moving wheel to the right of static witness mark)
//                                       increase the value below
//
const int stepsPerMin = 1537;  // increase value if clock display falls behind, reduce if gaining.                        ******

//      It is VERY important that your clock DOES NOT gain time (moving witness mark to left of static mark).
//
//                          If the clock is gaining, reduce the value above.
//
//                       The code can correct for loosing time, but not gaining
//
// =================================================================================================================
//



#define STEPPER_A 26  // 32
#define STEPPER_B 25  // 33
#define STEPPER_C 33  // 25
#define STEPPER_D 32  // 26
AccelStepper stepper(AccelStepper::FULL4WIRE, STEPPER_A, STEPPER_C, STEPPER_B, STEPPER_D);

#define nudgeButton 0
#define minuteButton 27

int count = -1;

void setup() {
  pinMode(nudgeButton, INPUT_PULLUP);   // enable/external button on ESP32 set to input
  pinMode(minuteButton, INPUT_PULLUP);  // external button on ESP32 set to input

  Wire.begin(21, 22);    // start iic
  Serial.begin(115200);  // start output to pc screen
  while (!Serial) {};
  // settup stepper parameters. Change these to suit your stepper if you want
  stepper.setMinPulseWidth(20);
  stepper.setMaxSpeed(600.0);
  stepper.setSpeed(600);
  stepper.setAcceleration(2000.0);
  stepper.setCurrentPosition(0);

  delay(2000);                                          // allow serial port to establish
  Serial.println("Set the hours and tens of minutes");  // user to set hours and tens of minutes manually
  Serial.println("on the Triaxial Clock to 11:5_");
  Serial.println("then press & release minute button to continue");

  while (digitalRead(minuteButton) == 1) {}  // wait for user to push button
  delay(250);
  while (digitalRead(minuteButton) == 0) {}  // wait for user to release button

  delay(250);  // use nudgeButton for user to set start position
  Serial.println();
  Serial.println("Press and hold the nudge button on the ESP32 to slowly rotate the minutes dial");
  Serial.println("so the clock reads 12:00 then release the button");

  while (digitalRead(nudgeButton)) {}  // wait for userto push button
  Serial.println(" we are moving.....");

  bool j = digitalRead(nudgeButton);  // run stepper while button pushed
  delay(15);                          //debounce
  while (!j) {
    stepper.setSpeed(100);
    stepper.move(10);
    stepper.run();
    j = digitalRead(nudgeButton);
  }

  stepper.stop();
  stepper.setCurrentPosition(0);
  delay(250);

  Serial.println();
  Serial.println("Add your witness marks to minutes dial");  // userto add witnesss mark
  Serial.println("Press Minute button again to start simulation");
  while (digitalRead(minuteButton)) {}  // wait for button push to continue

}  // end setup

void loop() {

  if (stepper.distanceToGo() == 0) {  // if stepper at 0 set for another minute run
    count++;
    Serial.print("Waiting ");
    Serial.println(count);
    delay(100);
    stepper.setCurrentPosition(0);
    stepper.moveTo(stepsPerMin);


    if (count == 10) {  // print to screen at 10 minute run time
      Serial.println("10 mins reached - one complete rotation of minutes");
      delay(3000);
    }

    if (count == 60) {  // print to screen at 60 minute run time
      Serial.println("60 mins reached");
      delay(3000);
    }


    if (count == 720) {  // print to screen at 12 hour run time and stop
      Serial.println();
      Serial.println("12 hours reached. End of simulation");
      Serial.println("if your clock is behind (witness mark on dial to the right of the static witness mark)");
      Serial.println("then increase stepsPerMin value found at top of code");
      Serial.println("IMPORTANT - your clock must not gain time");

      while (true) {}
    }
  }

  bool running = stepper.run();  // turn off stepper output if not running, reduce current and heat.
  if (!running)
    stepper.disableOutputs();
}

// put function definitions here:
