#include "myStepperDriver.h"

uint32_t timerTop32virtual;
uint32_t timeThreshold;
uint8_t  motorPattern;
#define  MOTOR_UPDATE_INTERVAL (1000)





/*******************************************************************************************************************
 * This function demonstrates with the remainder of the main loop how callback function can be used. First one has to declare a void function
 * that requires no arguments. This fuction
 */
static void
endPosReadched ()
{
  Serial.println ("Motor position reached / rotation stopped");
}






/*******************************************************************************************************************
 * Initialization is performed 'the Arduino way'. This is less efficient as direct PORT I/O access, but more universa over boards.
 */
void
setup ()
{
  motorShieldInit ();
  Serial.begin (115200);                                                //This is optional: allow use of serial port at 115200BPS.
  motorCallBackPositionReached (endPosReadched);                        //Optional, only available if the Timer update is handled by the user code.
  timeThreshold = millis ();
  motorPattern = 0;
  Serial.println ("Every value displayed is the 'idle' count");
  Serial.println ("where the AVR is not doing anything");
  #ifdef MOTOR_TIMER1
    Serial.println ("Timer1 used");
  #endif
  #ifdef MOTOR_TIMER3
    Serial.println ("Timer3 used");
  #endif
  #ifdef MOTOR_TIMER4
    Serial.println ("Timer4 used");
  #endif
  #ifdef MOTOR_TIMER5
    Serial.println ("Timer5 used");
  #endif
  DEBUGPRINT (("DDR = %02X", DDRL));
  DEBUGPRINT (("PORTL = %02X", PORTL));
}





/*******************************************************************************************************************
 * This is a template how to use the motor driver. As can be seen, we send only one time a command to it.          *
 * From that moment, the loop function doesn't perform anything else. The motor keeps on spinning based on the     *
 * provided parameters. In a typical use case, one can make some decision based on what happens in the main loop   *
 * (for instance, use optical sensors) and those lead into a decision that drives the motor.                       *
 *******************************************************************************************************************
 */
void
loop ()
{
  static uint32_t idleCount = 0;
  uint32_t now = millis ();
  if (now < timeThreshold)
  {
    ++idleCount;                                                        //Nothing to do, just increment idlecount.
  //motorTimerUpdateCheck ();                                           //If one wants to use the callback function as implemented above
  //                                                                    //One needs to remove MOTOR_CTRL_IRQ_TIMING from motorSetSpeed and
  //                                                                    //call motorTimerUpdateCheck every ~30-50ms from loop function.
  }
  else
  {                                                                     //Once in a while, when operation times out, change motor settling.
    switch (motorPattern)
    {
    case 0: Serial.println ("Speeding Up normal");
            #ifdef DEBUG_BAUDRATE
              serDbgPrint ("MotorStatus: %02X", motorReadStatus ());
            #endif
            motorSetSpeed (  MOTOR_CTRL_SPEED_VARIABLE
                           | MOTOR_CTRL_IRQ_TIMING
                           | MOTOR_CTRL_VARIABLE_PWR
                         //| MOTOR_CTRL_ENDPOINT_MILLIS
                         //| MOTOR_CTRL_DIRECTION
                           | MOTOR_CTRL_FASTER                          //Increase speed: TOP register is subtracted with decrease value.
                           | MOTOR_CTRL_DRV_EN,
                          4800000UL,                                    //uint32_t: Virtual 32-bit timer TOP to apply motor steps; 0 = STOP motor.
                          0UL,                                          //uint32_t: Limits amount of steps to execute (0 = never stop) or amount of millis to execute.
                          2385000UL,                                    //uint32_t: Virtual 32-bit correction on timerTop32Virtual.
                          MOTOR_UPDATE_INTERVAL,                        //uint16_t: Every xx ms, the correction is applied.
                          11);                                          //uint16_t: After this amount of mods has been reached, mod stops.
            timeThreshold = now + 15000;                                //15s after init, this command times out.
            break;
    case 1: Serial.println ("Slowing down normal");
            #ifdef DEBUG_BAUDRATE
              serDbgPrint ("MotorStatus: %02X", motorReadStatus ());
            #endif
            motorSetSpeed ( MOTOR_CTRL_SPEED_VARIABLE
                           | MOTOR_CTRL_IRQ_TIMING
                           | MOTOR_CTRL_VARIABLE_PWR
                         //| MOTOR_CTRL_ENDPOINT_MILLIS
                         //| MOTOR_CTRL_DIRECTION
                           | MOTOR_CTRL_SLOWER                          //Reducee speed: TOP register is subtracted with decrease value.
                           | MOTOR_CTRL_DRV_EN,
                          32332UL,                                      //uint32_t: Virtual 32-bit timer TOP to apply motor steps; 0 = STOP motor.
                          0UL,                                          //uint32_t: Limits amount of steps to execute (0 = never stop) or amount of millis to execute.
                          2329UL,                                       //uint32_t: Virtual 32-bit correction on timerTop32Virtual.
                          MOTOR_UPDATE_INTERVAL,                        //uint16_t: Every xx ms, the correction is applied.
                          11);                                          //uint16_t: After this amount of mods has been reached, mod stops.
            timeThreshold = now + 10000;                                //10s after init, this command times out.
            break;
    case 2: Serial.println ("Speeding Up reverse");
            #ifdef DEBUG_BAUDRATE
              serDbgPrint ("MotorStatus: %02X", motorReadStatus ());
            #endif
            motorSetSpeed (  MOTOR_CTRL_SPEED_VARIABLE
                           | MOTOR_CTRL_IRQ_TIMING
                           | MOTOR_CTRL_VARIABLE_PWR
                         //| MOTOR_CTRL_ENDPOINT_MILLIS
                           | MOTOR_CTRL_DIRECTION
                           | MOTOR_CTRL_FASTER                          //Increase speed: TOP register is subtracted with decrease value.
                           | MOTOR_CTRL_DRV_EN,
                          4800000UL,                                    //uint32_t: Virtual 32-bit timer TOP to apply motor steps; 0 = STOP motor.
                          0UL,                                          //uint32_t: Limits amount of steps to execute (0 = never stop) or amount of millis to execute.
                          2385000UL,                                    //uint32_t: Virtual 32-bit correction on timerTop32Virtual.
                          MOTOR_UPDATE_INTERVAL,                        //uint16_t: Every xx ms, the correction is applied.
                          11);                                          //uint16_t: After this amount of mods has been reached, mod stops.
            timeThreshold = now + 20000;                                //20s after init, this command times out.
            break;
    case 3: Serial.println ("Slowing down reverse");
            #ifdef DEBUG_BAUDRATE
              serDbgPrint ("MotorStatus: %02X", motorReadStatus ());
            #endif
            motorSetSpeed (  MOTOR_CTRL_SPEED_VARIABLE
                           | MOTOR_CTRL_IRQ_TIMING
                           | MOTOR_CTRL_VARIABLE_PWR
                         //| MOTOR_CTRL_ENDPOINT_MILLIS
                           | MOTOR_CTRL_DIRECTION
                           | MOTOR_CTRL_SLOWER                          //Decrease speed: TOP register is subtracted with decrease value.
                           | MOTOR_CTRL_DRV_EN,
                          32332UL,                                      //uint32_t: Virtual 32-bit timer TOP to apply motor steps; 0 = STOP motor.
                          0UL,                                          //uint32_t: Limits amount of steps to execute (0 = never stop) or amount of millis to execute.
                          2329UL,                                       //uint32_t: Virtual 32-bit correction on timerTop32Virtual.
                          MOTOR_UPDATE_INTERVAL,                        //uint16_t: Every xx ms, the correction is applied.
                          11);                                          //uint16_t: After this amount of mods has been reached, mod stops.
            timeThreshold = now + 10000;                                //10s after init, this command times out.
            break;
    case 4: Serial.println ("Stopping");
            motorSetSpeed (MOTOR_CTRL_DRV_EN);                          //Default is motor stopped, but keep drive enabled.
            #ifdef DEBUG_BAUDRATE
              serDbgPrint ("MotorStatus: %02X", motorReadStatus ());
            #endif
            timeThreshold = now + 3500;                                 //Keep motor stopped for 3.5s.
            break;
    case 5:
            timeThreshold = now + 3500;                                 //3.5s
            break;
    case 6:
            timeThreshold = now + 4000;                                 //4s
            break;
    case 7: Serial.println ("250 RPM from stop");
            motorSetSpeed (MOTOR_CTRL_DRV_EN,                           //250 / 60 * 200 steps /s.
            19200UL);
            timeThreshold = now + 4500;                                 //4.5s
            break;
    case 8: Serial.println ("500 RPM");
            motorSetSpeed (MOTOR_CTRL_DRV_EN,                           //500 / 60 * 200 steps /s.
            9600UL);
            timeThreshold = now + 10000;                                //10s after init, this command times out.
            break;
    case 9: Serial.println ("Stopping");
            motorSetSpeed (MOTOR_CTRL_DRV_EN);                          //Default is motor stopped, but keep drive enabled.
            timeThreshold = now + 5000;                                 //5s
            break;
    default: break;
    }
    ++motorPattern;
    if (motorPattern > 10) motorPattern = 0;
    Serial.println (idleCount);
  }
}

