#ifndef __STEPMOTORDRIVERA4988_H__
  #define __STEPMOTORDRIVERA4988_H__

  #include "arduino.h"

  /********************************************************************************************************
   *    Remove the comments from the intended motor drivers. There are maximal 4 stepper motors each driven by A4988.
   *    The STEP pin has a fixed position since the 16bit hardware timers are used to generate these STEP pulses.
   *    (that pin is limit by the AVR designers). See the documentation.
   *    Note the number correlates to the used 16bit AVR timer. If this timer is used by anything else in your application
   *    you should not use that specific timer since it will lead to conflicts.
   */
//#define MOTOR_TIMER_1                                                 //[Uno] D9 PB1/OC1A - [Mega] D11 PB5/OC1A.
//#define MOTOR_TIMER_3                                                 //Not available     - [Mega] D5  PE3/OC3A.
//#define MOTOR_TIMER_4                                                 //Not available     - [Mega] D6  PH3/OC4A.
  #define MOTOR_TIMER_5                                                 //Not available     - [Mega] D46 PL3/OC5A.




  /********************************************************************************************************
   *    Enumerations.
   */
  enum MOTORSTEPSELECTION
  {
    MOTORSTEP_FULL,
    MOTORSTEP_HALF,
    MOTORSTEP_QUARTER,
    MOTORSTEP_EIGHT,
    MOTORSTEP_SIXTEENTH,
  };

  enum MOTORUPDATE
  {
    MOTORUPDATE_NOW,
    MOTORUPDATE_SYNCHRONIZED,
  };


  /********************************************************************************************************
   *    Generic prototypes. These are shared for every available motor.
   */
  int8_t   stepMotorInit ();                                            //Set I/O configuration, enable the A4988.
  uint32_t motorTimerGetIOclocksPerSecond ();                           //Returns the amount of IO Clocks per second (in most cases this will be 16000000).
  uint32_t motorTimerRPMtoTimerTop32 (float rpm, unsigned int steps_revolution);//Returns the virtual 32bit Timer output compare value for a certain RPM and steps per revolution.
                                                                        //Note: since this function is not aware what motor is used, the steps must be multiplied vs. the mode.
                                                                        //Ex. A 200 step/revolution motor in half step mode requires 400 steps per revolution.

  /********************************************************************************************************
   *    Note one may opt to hard-wire A4988 MSx, Enable, Sleep & Reset pins instead of connecting to the Arduino (to reduce used I/O pins).
   *    Comment out the #defines and the code will exclude to drive those pins. Take care one should not select A4988 Microstep mode that is
   *    not possible to drive because of hard-wired A4988 pins! Reducing the pins will also reduce the code size, since there is no need anymore
   *    generate object code to drive these pins.
   */
  #ifdef MOTOR_TIMER_1
    int8_t stepMotor1TimerUpdate (uint32_t timTop32);                   //Step pulses on Digital D11 (Mega) or D9 (Uno).
    int8_t stepMotor1SetStepMode (MOTORSTEPSELECTION sel, MOTORUPDATE u = MOTORUPDATE_SYNCHRONIZED);
    int8_t stepMotor1Status ();                                         //Return motor spinnig (=10), position reached (=1), driver active motor not spinning (=0), A4988 not driving (=-1), A4988 Sleeping (=-2).
    void stepMotor1Sleep ();                                            //Deactivate motor driver power stage.
    void stepMotor1WakeUp ();                                           //Activate motor driver power stage.
    void stepMotor1DriverEnable ();                                     //Drive the enable pin active.
    void stepMotor1DriverDisable ();                                    //Drive the enable pin inactive.
    void stepMotor1Reset ();                                            //Reset A4988 and reset counters.
    void stepMotor1EndPointEnable (int32_t endpoint);                   //Enable certain endpoint (=motor steps).
    void stepMotor1EndPointDisable ();                                  //Disable endpoint detecttion.
    void stepMotor1Direction (uint8_t dl);                              //Set direction pin high or low.
    int32_t stepMotor1GetPosition ();                                   //Readback present motor position in full steps.
  //#define A4988_1_SLEEP     44                                        //Update these Digital I/O pins vs your motor connection.
  //#define A4988_1_MS1       45
  //#define A4988_1_MS2       46
  //#define A4988_1_MS3       47
  //#define A4988_1_ENABLE    49
  //#define A4988_1_RESET     50
    #define A4988_1_DIR       48
  #endif
  #ifdef MOTOR_TIMER_3                                                  //Not available on Uno.
    int8_t stepMotor3TimerUpdate (uint32_t timTop32);                   //Step pulses on Digital D5 (Mega).
    int8_t stepMotor3SetStepMode (MOTORSTEPSELECTION sel, MOTORUPDATE u = MOTORUPDATE_SYNCHRONIZED);
    int8_t stepMotor3Status ();
    void stepMotor3Sleep ();
    void stepMotor3WakeUp ();
    void stepMotor3DriverEnable ();
    void stepMotor3DriverDisable ();
    void stepMotor3Reset ();
    void stepMotor3EndPointEnable (int32_t endpoint);
    void stepMotor3EndPointDisable ();
    void stepMotor3Direction (uint8_t dl);
    int32_t stepMotor3GetPosition ();
  //#define A4988_3_SLEEP     37                                        //Update these Digital I/O pins vs your motor connection.
  //#define A4988_3_MS1       38
  //#define A4988_3_MS2       39
  //#define A4988_3_MS3       40
  //#define A4988_3_ENABLE    42
  //#define A4988_3_RESET     43
    #define A4988_3_DIR       41
  #endif
  #ifdef MOTOR_TIMER_4                                                  //Not available on Uno.
    int8_t stepMotor4TimerUpdate (uint32_t timTop32);                   //Step pulses on Digital D6 (Mega).
    int8_t stepMotor4SetStepMode (MOTORSTEPSELECTION sel, MOTORUPDATE u = MOTORUPDATE_SYNCHRONIZED);
    int8_t stepMotor4Status ();
    void stepMotor4Sleep ();
    void stepMotor4WakeUp ();
    void stepMotor4DriverEnable ();
    void stepMotor4DriverDisable ();
    void stepMotor4Reset ();
    void stepMotor4EndPointEnable (int32_t endpoint);
    void stepMotor4EndPointDisable ();
    void stepMotor4Direction (uint8_t dl);
    int32_t stepMotor4GetPosition ();
  //#define A4988_4_SLEEP     29                                        //Update these Digital I/O pins vs your motor connection.
  //#define A4988_4_MS1       30
  //#define A4988_4_MS2       31
  //#define A4988_4_MS3       32
  //#define A4988_4_ENABLE    34
  //#define A4988_4_RESET     35
    #define A4988_4_DIR       33
  #endif
  #ifdef MOTOR_TIMER_5                                                  //Not available on Uno.
    int8_t stepMotor5TimerUpdate (uint32_t timTop32);                   //Step pulses on Digital D46 (Mega).
    int8_t stepMotor5SetStepMode (MOTORSTEPSELECTION sel, MOTORUPDATE u = MOTORUPDATE_SYNCHRONIZED);
    int8_t stepMotor5Status ();
    void stepMotor5Sleep ();
    void stepMotor5WakeUp ();
    void stepMotor5DriverEnable ();
    void stepMotor5DriverDisable ();
    void stepMotor5Reset ();
    void stepMotor5EndPointEnable (int32_t endpoint);
    void stepMotor5EndPointDisable ();
    void stepMotor5Direction (uint8_t dl);
    int32_t stepMotor5GetPosition ();
    #define A4988_5_SLEEP     22                                        //Update these Digital I/O pins vs your motor connection.
    #define A4988_5_MS1       23
    #define A4988_5_MS2       24
    #define A4988_5_MS3       25
    #define A4988_5_ENABLE    27
    #define A4988_5_RESET     28
    #define A4988_5_DIR       26
  #endif
#endif
