/*
 * RAto       Arduino code to move telescope eq mount Right Ascension at
 * Version 1.0 for Thiagogó - include modifications ratio and button settings
 *             1x and detect button press to cycle among speeds 1x->8x->-6x->-stop
 *            Tracking speed select long press +1 Second - sideral 23h56m4s ->- moon 24h48m ->- Sun 24h
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *  Original - by gspeed @ astronomia.com / qde / cloudynights.com forum           
 *  Wirings: https://mappite.org/stars/RAto-drv8825.png
 *  This code or newer versions at https://mappite.org/stars/RAto.ino 
 *
 *  
 *  This code is free software under GPL v3 License use at your risk and fun ;)
 *
 * UPDATE: new project aGotino can be used for just RA tracking as well
 *         check for updates on
 *         https://github.com/mappite/aGotino
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * How to calculate STEP_DELAY to drive motor at right speed to follow stars
 * 
 * Worm Ratio  100    // 100 EQ1
 * Pulley/Gear Ratio 3:1  // depends on your pulley setup e.w. 60T/20T = 3:1 
 * Steps per revolution  400  // or 200, usually (my is 200 1.8º)
 * Microstep 62     // make sure to enable pins in driver
 *
 * Steps per degree  10666  // WormRatio*OtherRatio*StepsPerRevolution*Microsteps/360
 *                          // = number of microsteps to rotate the scope by 1 degree
 *
 * STEP_DELAY  22439  // 1000000*((23*60*60+56*60+4)/360)/stepsPerDegree
 *                    // = microseconds to advance a microstep
 *                    // 23*60*60+56*60+4 is the number of secs for earth 360deg rotation
 *
 * STEP_DELAY  23251  // 1000000*((24*60*60+48*60)/360)/stepsPerDegree
 *                    // = microseconds to advance a microstep
 *                    // 24*60*60+48*60 this is the number relative to the Moon being in the same position after 1 rotation of the earth.
 *
 * STEP_DELAY  22501  // 1000000*((24*60*60)/360)/stepsPerDegree
 *                    // = microseconds to advance a microstep
 *                    // 24*60*60 this is the number relative to the Sun being in the same position after 1 rotation of the earth.
 *
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 */
// in micros, step duration to follow stars
unsigned long STEP_DELAY = 22439; //22439 in 64 steps or 44879 in 32 steps
// pin connections
const int dirPin = 4;
const int stepPin = 3;
const int Enable = 5;
    
const int ledPin = LED_BUILTIN;     
//botão
const int buttonPin = 2; 
unsigned char buttonState;
unsigned long duration;
unsigned long resettime;
int tracking = 0;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 20; //debounce botão
//som
#define tone_out1 8
#define tone_out2 9
short speaker_pin1 = 8;                //arduino speaker output +
short speaker_pin2 = 9;                //arduino speaker output -
// buffer time in micros: when we are at STEP_DELAY_MIN micros from having
// to change pulse status let's call (blocking) delayMicroseconds to allow a smooth pulse signal
// this must be less than 16383 and more than what logic does at each loop to honor STEP_DELAY
unsigned long STEP_DELAY_MIN = 100; 
unsigned long lastTime; // micros, last time pulse has changed status 
boolean stepPinStatus = false;
int velocity = 0; // speed is a reserved keyword ;)
unsigned long i = 0; // for debug
void setup() {
  Serial.begin(19200);
  Serial.print("RAto: READY");
  // init Driver Motor pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(Enable, OUTPUT);
  // Set motor direction clockwise (HIGH)
  digitalWrite(dirPin, HIGH);
  // make sure no signal is sent
  digitalWrite(stepPin, LOW); // no signal
  digitalWrite(Enable, HIGH); // driver OFF
  // init Button pin as Input Pullup so no need resistor
  pinMode(buttonPin, INPUT_PULLUP);
  // init led and turn on for 0.5 sec
    pinMode(tone_out1, OUTPUT);  // Dinâmica pin8 de saída +
    pinMode(tone_out2, OUTPUT);  // Speaker pin9 saída -
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.print(" and RUNNING with pulse length: ");
  Serial.println(STEP_DELAY);
  // Resolution is 4microsecs on 16Mhz board
  lastTime = micros();
  play_welcome_beep();
}
// Saudações de áudio
void play_welcome_beep()                 
{
    for (int aa=100;aa<=800;aa=aa+100)
    {
        tone(tone_out1,aa,200);       
        tone(tone_out2,aa+3,200);
        delay(50);
    }
}
//fim saldaçnao de audio
void runStep(long stepDelay) {
    unsigned long halfStepDelay = stepDelay/2; // duration of each pulse
    unsigned long dt  = micros() - lastTime;   // delta time elapsed since previus stepPin status change
    // micros() overflow after approximately 70 minutes but "-" logic above will work anyway to calculate dt 
    
    if ( dt > halfStepDelay)  { // no luck, too fast, we can't honor halfStepDelay.
      Serial.print("Can't honor the speed, dt: ");
      Serial.println(dt);
    } else  if ( dt > halfStepDelay-STEP_DELAY_MIN) { // need to switch pulse in halfStepDelay-dt micros, let's do it:
      // remaining delay to keep current pin status to honor halfStepDelay
      delayMicroseconds(halfStepDelay-dt);// which is less than STEP_DELAY_MIN
      //change pin status 
      stepPinStatus = !stepPinStatus;
      digitalWrite(stepPin, (stepPinStatus?HIGH:LOW));
      /* debug 
      i++;
      if (i == 1000) { 
        unsigned long pulseDuration2 = (micros()-lastTime);
        Serial.println("logB:");
        Serial.print("stepDelay: "); Serial.println(stepDelay);
        Serial.print("halfStepDelay: "); Serial.println(halfStepDelay);
        Serial.print("lastTime: ");Serial.println(lastTime);
        Serial.print("dt: "); Serial.println(dt);
        Serial.print("delayMicroseconds:"); Serial.println((halfStepDelay-dt));    
        Serial.print("pulseDuration2: "); Serial.println(pulseDuration2);    
        delay(5000);  
        i= 0;
      }
      */
      lastTime = micros(); // last time we updated the pin status
    }
}
void loop() {
   if (velocity != 0){
  runStep(STEP_DELAY/velocity);
}
  /* 
   * logic executed at each loop must take less than (STEP_DELAY/2-STEP_DELAY_MIN) 
   * and less than STEP_DELAY_MIN. This is just a an IF for now...
   */
  
  
  int currentState = (digitalRead (2));
      if (currentState != buttonState) {
           duration = millis();
           resettime = millis();
      }
        if(currentState ==LOW){
          if ((millis() - duration >20) && (millis() - duration < 1000)) {
            
            //troca velocidade do acompanhamento
     Serial.print("New Velocity: ");
     // 1x -> 8x -> -6x
     if (velocity == 1 && (digitalRead (2)==HIGH)) { 
        velocity = 8;
        digitalWrite(LED_BUILTIN, HIGH);
        tone(tone_out1,1800,40); 
        delay(80);
        digitalWrite(dirPin, HIGH);
        digitalWrite(Enable, LOW);
     } else if  (velocity == 8 && (digitalRead (2)==HIGH)) {
        velocity = 6;
        digitalWrite(LED_BUILTIN, HIGH);
        tone(tone_out1,1800,40); 
        delay(80);
        digitalWrite(dirPin, LOW); // change direction
     } else if  (velocity == 6 && (digitalRead (2)==HIGH)) {
        velocity = 0;
        digitalWrite(LED_BUILTIN, HIGH);
        tone(tone_out1,1800,40); 
        delay(80);
        tone(tone_out1,1800,40); 
        delay(80);
        tone(tone_out1,1800,40); 
        delay(80);
        digitalWrite(dirPin, HIGH);
        digitalWrite(Enable, HIGH);
     
     } else if  (velocity == 0 && (digitalRead (2)==HIGH)) {
        velocity = 1;
        digitalWrite(LED_BUILTIN, HIGH);
        tone(tone_out1,1800,40); 
        delay(80);
        tone(tone_out1,1800,40); 
        delay(80);
        digitalWrite(dirPin, HIGH);
        digitalWrite(Enable, LOW);
     }
     Serial.println(velocity);
     digitalWrite(LED_BUILTIN, LOW);
     lastTime = micros(); // reset time 
 
          }
          
          if (millis() - duration > 1100) {
            Serial.print("New Tracking: ");
            //troca modo de acompanhamento
             if (tracking == 0){
              STEP_DELAY = 23251; //moon tracking
              tracking = 1;
              digitalWrite(LED_BUILTIN, HIGH);
            tone(tone_out1,1000,250);
            tone(tone_out2,1003,250);
            delay(200);
            tone(tone_out1,2000,250);
            tone(tone_out2,2003,250);
            delay(200);
            tone(tone_out1,1000,250);
            tone(tone_out2,1003,250);
            delay(200);
            tone(tone_out1,2000,250);
            tone(tone_out2,2003,250);
            
              }
              else if (tracking == 1){
              STEP_DELAY = 22501; //Sun tracking
              tracking = 2;
              digitalWrite(LED_BUILTIN, HIGH);
              tone(tone_out1,1000,250);
              tone(tone_out2,1003,250);
              delay(200);
              tone(tone_out1,2000,250);
              tone(tone_out2,2003,250);
               delay(200);
              tone(tone_out1,1000,250);
              tone(tone_out2,1003,250);
               delay(200);
              tone(tone_out1,2000,250);
              tone(tone_out2,2003,250);
              delay(200);
              tone(tone_out1,1000,250);
              tone(tone_out2,1003,250);
               delay(200);
              tone(tone_out1,2000,250);
              tone(tone_out2,2003,250);
              }
              else if (tracking == 2){
              STEP_DELAY = 22439; //Sideral tracking
              tracking = 0;
              digitalWrite(LED_BUILTIN, HIGH);
              tone(tone_out1,1000,250);
              tone(tone_out2,1003,250);
               delay(200);
              tone(tone_out1,2000,250);
              tone(tone_out2,2003,250);
               delay(200);
              }
            digitalWrite(LED_BUILTIN, LOW);
            Serial.println(tracking);
              Serial.print(" and RUNNING with pulse length: ");
              Serial.println(STEP_DELAY);
            duration = millis();
            lastTime = micros(); // reset time 
          }
        }
        buttonState = currentState;
  
 
}