#ifndef HARDWARE_H
#define HARDWARE_H
/***************************************************************************
hardware.h - Created by Peter Mauger 03/04/01
last modified 12/10/01

hardware contains all of the functions that manipulate hardware on the eyebot.
***************************************************************************/

#include "include.h"

/************************* Functions to manipulate the control surface structure */

/* Init_Ctrl_Surface initialises a servo and sets the limits and neutral point
* inputs:  ctrl_surface_name->the name of the servo you wish to initialise (servoconsts)
* returns: control surface struct
*/
error Init_Ctrl_Surface(servoconsts ctrl_surface_name, ctrlsurface *ctrl_surface);

/* Get_Angle retrieves the angle the control surface is currently set at
* inputs:  ctrl_surface->structure containing the control surface info
* returns: angle the surface is set to
*/
double Get_Angle(ctrlsurface ctrl_surface);

/* Set_Angle sets the angle the control surface should be set to. This will be 
* updated to an actual servo value when Update_Servo is called.
* inputs:  ctrl_surface->structure containing the control surface info
*	   angle->the angle the control surface should be set to
*	   mode->if the mode is SET then use the absolute limits
*		 if NORMAL then use the user defined limits
* returns: LIMITERROR if the angle is outside of the servo's MAX/MIN limit, 
*	   NOERROR otherwise
*/
error Set_Angle(ctrlsurface *ctrl_surface, double angle, anglesetmode mode);

/* Get_Servo returns the handle for the servo so that it can be manipulated
* inputs:  ctrl_surface->the control surface you wish to retrieve the servo from
* returns: the handle of the servo that was requested.
*/
ServoHandle Get_Servo(ctrlsurface ctrl_surface);

/* Get_Min_Limits returns the minimum value the servo should be set to
* inputs:  ctrl_surface->structure containing the control surface info
* returns: the minimum limit of that servo
*/
double Get_Min_Limit(ctrlsurface ctrl_surface);

/* Set_Min_Limits sets the minimum value the servo can be set to
* inputs:  ctrl_surface->structure containing the control surface info
*	   min_limit->the minimum value the servo should be set to
* returns: ABSOLUTELIMITERROR if the limit entered is lower than the possible minimum,
*	   LIMITCROSS if the limit entered is higher than the current maximum limit,
*	   NOERROR otherwise
*/
error Set_Min_Limit(ctrlsurface *ctrl_surface, double min_limit);

/* Get_Max_Limits returns the maximum value the servo should be set to
* inputs:  ctrl_surface->structure containing the control surface info
* returns: the maximum limit of that servo
*/
double Get_Max_Limit(ctrlsurface ctrl_surface);

/* Set_Max_Limits sets the maximum value the servo can be set to
* inputs:  ctrl_surface->structure containing the control surface info
*	   max_limit->the maximum value the servo should be set to
* returns: ABSOLUTELIMITERROR if the limit entered is higher than the possible maximum,
*	   LIMITCROSS if the limit entered is lower than the current minimum limit,
*	   NOERROR otherwise
*/
error Set_Max_Limit(ctrlsurface *ctrl_surface, double max_limit);

/* Get_Neutral_Point returns the neutral angle of the control surface
* inputs:  ctrl_surface->contains the neutral point
* returns: the neutral point of the control surface
*/
double Get_Neutral_Point(ctrlsurface ctrl_surface);

/* Set_Neutral_Point sets the neutral point of the control surface
* inputs:  ctrl_surface->contains the neutral point
*	   neutral_point->the neutral angle of the control surface
* returns: LIMITERROR if the neutral point is outside of the max and min limits
*	   NOERROR otherwise
*/
error Set_Neutral_Point(ctrlsurface *ctrl_surface, double neutral_point);

/* Move_Ctrl_Surface_Servo reads the angle of a control surface and the servo to
* that angle.
* inputs:  ctrl_surface->contains the angle
* returns: SERVOERROR if the servo was unable to be set to that value
*	   NOERROR if the servo was set correctly
*/
error Move_Ctrl_Surface_Servo(ctrlsurface ctrl_surface);

/* Establish_Servo_Limits sets the three limits of the control surface passed in.
* inputs:  ctrl_surface->contains the settings for the control surface
* returns: An error indicating a problem has occured
*	   NOERROR otherwise
*/
error Establish_Servo_Limits(ctrlsurface *ctrl_surface);

/* Test_Servo_Limits tests the accuracy of the limit settings for the control surface
* inputs:  ctrl_surface->contains limit information
*	   valid->passes the success or failure of the test out
* returns: An error if one occured in the test
*	   NOERROR otherwise
*/
error Test_Servo_Limits(ctrlsurface ctrl_surface, bool *valid);

/* Convert_Servo2Angle converts a servo setting into a control surface angle
* inputs:  ctrl_surface->contains the limit settings
*	   setting->the servo setting to be converted into an angle
*	   angle->the angle that the setting was converted into
* returns: IDERROR if the servo id was not recognised
*	   NOERROR otherwise
*/
error Convert_Servo2Angle(ctrlsurface ctrl_surface, int setting, double *angle);

/* Servo2Angle converts a servo setting into a control surface angle
* inputs:  ctrl_surface->contains the limit settings
*	   angle->the angle to be converted into a setting 
*	   setting->the servo setting that the angle was converted into
* returns: IDERROR if the servo id was not recognised
*	   NOERROR otherwise
*/
error Convert_Angle2Servo(ctrlsurface ctrl_surface, double angle,  int *setting);

/***************************************** Other hardware manipulating functions */

/* Initialise_Plane performs all of the required initialisation steps for the plane to be ready for flight.
* It will provide all feedback required through the eyebot LCD screen
* inputs:  plane->pointer to plane struct which will be initialised and contain all required info for flight
* returns: the error that occured or 
*	   NOERROR if initialisation was successfull	   
*/
error Initialise_Plane(planestate *plane);

/* Check_Switch checks the state of the manual->autopilot switch
* returns: switchstate->state of the switch (OFF->manual ON->autopilot)
*/
switchstate Check_Switch(void);

/* Check_Input determines whether an input has been received from either input
* device (buttons or remote) and returns an identifier for the button if it has 
* been pushed
* returns: KEY1 to KEY4 representing the buttons on the eyebot
*/
int Check_Input();

/* Shut_Down terminates all hardware so that it can be reused later
* inputs:  plane->contains handles for hardware
*/
void Shut_Down(planestate plane);

#endif
