/****************************************************************************
 Header file for Drivetrain Module

 Notes
 In general, "Power" is different from duty cycle, in that the input "power"
 could be scaled, offset, etc. to maintain a consistent output speed as the
 batteries die.  Power typically ranges from -100 (reverse) to +100 (forward),
 while duty cycle (0-255) and motor direction (0/1) are calculated and set
 separately.

 Direction scales from +100 (left, CCW in place) to 0 (straight) to -100
 (right, CW in place).  Intermediate values represent driving in an arc, with
 a more extreme direction being a tighter radius.

 The only permissible drive actions taken by external functions are timed (except
 Drive_Stop). This prevents a drive event from being initiated without a scheduled
 timeout. A timed drive event does not need to finish before another is initiated.
 ****************************************************************************/
#ifndef SMDrivetrain_H
#define SMDrivetrain_H

// Event Definitions
#include "SMEvents.h"

// Interfaced
#include "SMBeaconDetection.h"

#include "Servos.h"

// typedefs for the states
// State definitions for use with the query function
typedef enum { Drive_Waiting, Drive_Moving, Drive_BeaconAligning, Drive_BeaconTracking, Drive_Aiming} DriveState_t ;



typedef enum
{
    Forward = 100,
    Reverse = -100,

    Forwards = 100,  //optional, less preferred syntax
    Backwards = -100 //optional, less preferred syntax
} Direction_t;

typedef enum
{
    Left = 100,
    Right = -100,
    CCW = 100, //optional syntax
    CW = -100  //optional syntax
} TurnDirection_t;

// Public Function Prototypes

Event_t RunDriveSM( Event_t CurrentEvent );
void StartDriveSM ( Event_t CurrentEvent );
DriveState_t QueryDriveSM ( void );

/****************************************************************************
 Function
 QueryDriveTransitionFlag

 Returns
 1 if flag was set, 0 otherwise

 Description
 Checks to see if DrivetrainSM should make a state change
 ****************************************************************************/
unsigned char QueryDriveTransitionFlag(void);

/****************************************************************************
 Function
 Stop

 Description
 Stops motors, without creating a timed drive.
 ****************************************************************************/
void Drive_Stop(void);

/****************************************************************************
 Function
 Drive_Timed

 Parameters
 signed char Direction, signed char Power, unsigned int Timer (in ms)

 Description
 Initiates the robot driving in specified direction at specified power for
 specified time
 ****************************************************************************/
void Drive_Timed(signed char Direction, signed char Power, unsigned int Timer);

/****************************************************************************
 Function
 QueryDriveTimerFlag

 Returns
 1 if timer has expired, 0 otherwise

 Description
 Checks to see if drive timer has expired
 ****************************************************************************/
unsigned char QueryDriveTimerFlag(void);

/****************************************************************************
 Function
 Drive_AlignToBeacon

 Parameters
 Beacon_t Beacon - beacon to align to, signed char Angle - relative alignment
 angle (turns turret to achieve offset), unsigned char Power - inital turning
 speed.

 Description
 Angles turret and aligns to specified beacon
 ****************************************************************************/
void Drive_AlignToBeacon(Beacon_t Beacon, signed char Angle, unsigned char Power);

/****************************************************************************
 Function
 QueryDriveBeaconFound

 Returns
 1 if robot is aligning and the desired beacon is seen straight ahead

 Description
 checks for whether beacon alignment has been achieved
 ****************************************************************************/
unsigned char QueryDriveBeaconFound(void);

/****************************************************************************
 Function
 Drive_TrackBeacon

 Parameters
 Beacon_t Beacon - beacon to track, signed char Angle - relative alignment
 angle (turns turret to achieve offset), unsigned char Power - initial
 tracking power

 Description
 angles turret and initiates robot driving to desired beacon.  angling turret
 allows for approaching the beacon in an arced movement.  angle and power can
 be updated during tracking.
 ****************************************************************************/
void Drive_TrackBeacon(Beacon_t Beacon, signed char Angle, unsigned char Power);

/****************************************************************************
 Function
 QueryDriveBeaconLost

 Returns
 1 if beacon was lost during tracking, 0 otherwise

 Description
 Checks to see if beacon was lost during tracking
 ****************************************************************************/
unsigned char QueryDriveBeaconLost(void);

/****************************************************************************
 Function
 ReduceTrackingPower

 Parameters
 unsigned char divisor

 Description
 Reduces the current tracking power by a factor of Divisor, to a minimum of 25.
 ****************************************************************************/
void ReduceTrackingPower(unsigned char Divisor);

/****************************************************************************
 Function
 ReduceTrackingAngle

 Parameters
 unsigned char divisor

 Description
 Reduces the turret angle by a factor of divisor.
 ****************************************************************************/
void ReduceTrackingAngle(unsigned char Divisor);

/****************************************************************************
 Function
 Drive_Aim

 Parameters
 Beacon_t Beacon - beacon to aim at, signed char Angle - offset of where to
 aim relative to beacon, unsigned char Power - initial turning power

 Description
 Aims relative to specified beacon by specified angle.
 ****************************************************************************/
void Drive_Aim(Beacon_t Beacon, signed char Angle, unsigned char Power);

/****************************************************************************
 Function
 QueryDriveAimed

 Returns
 1 if aiming accomplished, 0 otherwise

 Description
 Checks to see if robot has aimed yet
 ****************************************************************************/
unsigned char QueryDriveAimed(void);

#endif /*SMDrivetrain_H */