/*! \file 
*	\details This file contains necessary definitions & macros	
*
*	\defgroup WheelchairControl Wheelchair control MCU software.
*	\details This group contains all source files for MCU of the wheelchair.  
*
*	\addtogroup  WheelchairControl
*	@{
*/

#ifndef _DEFINES	//Define once
#define _DEFINES

//Includes
#include <avr/io.h>

//Debug mode
//#define DEBUG		/*!<Uncomment to enable debugging using AVR studio's built-in debugger*/

//Assembler substitutes
#define GLOBAL_INTERRUPTS_ENABLE() 	asm("sei")	/*!<Enable global interrupts.*/
#define GLOBAL_INTERRUPTS_DISABLE()	asm("cli")	/*!<Disable global interrupts.*/
#define WATCHDOG_RESET()			asm("WDR")	/*!<Reset watchdog.*/
#define WATCHDOG_INITIALIZE()		WATCHDOG_RESET(); WDTCR = ( (1<<WDE) | 0x05 )	/*!<Watchdog reset & initialize (reset interval appr. 0.5 s).*/

//SRF08 constants
#define SRF08_RANGE 				(2500) /*!<SRF08 range in mm.*/
#define SRF08_GAIN 					(0x03) /*!<SRF08 gain.*/ 
#define SRF08_LOWEST_ADDR			(0xE0) /*!<Lowest possible address.*/
#define SRF08_HIGHEST_ADDR			(0xE8) /*!<Highest possible address.*/
#define SCL_CLOCK 					(50000UL)	/*!<I2C serial clock frequency.*/

//Wheels inputs
#define RIGHT_WHEEL_DIR 			( PIND & (1 << PD7) )	/*!<Direction signal of right wheel at PORTD.7.*/
#define LEFT_WHEEL_DIR 				( PIND & (1 << PD6) )	/*!<Direction signal of left wheel at PORTD.6.*/
#define RIGHT_WHEEL_STEP			( PIND & (1 << PD3) )	/*!<Right wheel STEP signal.*/
#define LEFT_WHEEL_STEP				( PIND & (1 << PD2) )	/*!<Light wheel STEP signal.*/

//Conversion constants
#define UCHAR_TO_RC_SIGNAL 			(247)	/*!<Offset to convert 0 - 255 values of unsigned char to 250 - 500 values of OCR1X of RC signal generator (128 + 247 = 375 -> stop motors).*/
#define SPEED_OFFSET				(128)	/*!<Zero speed offset.*/
#define REAR_CORRECTION_OFFSET		(128)	/*!<Offset of SRF08 rear correction constant.*/
#define REG_OUTPUT_MAX				(255)	/*!<Maximal possible output of the speed regulator.*/
#define REG_OUTPUT_MIN				(0)		/*!<Minimal possible output of the speed regulator.*/
#define INTEGRATOR_MAX				(2550)	/*!<Maximal integrator value	(10 * REG_OUTPUT_MAX).*/
#define INTEGRATOR_MIN				(-2550)	/*!<Minimal integrator value	(-10 * REG_OUTPUT_MAX).*/

//MCU clock frequency
#ifndef F_CPU
	#define F_CPU					(16e6)	/*!<CPU freq. 16 MHz.*/
#endif

//Car's steering wheel position
#define STEERING_WHEEL_LEFT			(FALSE)	/*!<Determines whether steering wheel of car is situated on the right (UK) or left side (rest of Europe).*/

//Signal LEDs
#define LED_IN						(1 << PA1)	/*!<UART in LED.*/
#define LED_OUT						(1 << PA2)	/*!<UART out LED.*/

//Blink LEDs for a specified period
#define BLINK_LEDS_MS(DURATION)		PORTA |= (LED_IN | LED_OUT); DELAY_MS(DURATION); PORTA &= ~(LED_IN | LED_OUT); DELAY_MS(DURATION) /*!<Blink LEDs for a specified period.*/

//Delay
#ifndef DEBUG
	#define	DELAY_US(DURATION)		_delay_us(DURATION)	/*!<Delay in microseconds.*/
	#define	DELAY_MS(DURATION)		_delay_ms(DURATION)	/*!<Delay in miliseconds.*/
#else
	#define	DELAY_US(DURATION);		//Do not use _delay_us() macro to enable debugging in AVR studio
	#define	DELAY_MS(DURATION);		//Do not use _delay_ms() macro to enable debugging in AVR studio	
#endif

//Odometry
#define PI_MRAD						(3141)	/*!<Pi in miliradians.*/
#define TWO_PI_MRAD					(6283)	/*!<2*pi in miliradians.*/
#define WHEEL_INCREMENT_SCALE		(10)	/*!<Wheel increment scale to improve resolution.*/

//Position regulator
#define REG_ANGLE_EPSILON			(0.1)	/*!<Allowed angle regulation error.*/
#define WTEMP_SCALE					(10)	/*!<Position regulator omega scale to increase resolution.*/
#define OMEGA_SCALE					(0.1)	/*!<Wall-following regulator omega scale to increase resolution.*/

//UART WATCHDOG
#define UART_WATCHDOG_TIMEOUT		(20)	/*!<Watchdog timeout in multiples of 50 ms.*/

//Timers control
#define TIMER_0_RESET()				(TCNT0 = 0x00);	/*!<Reset RX timer.*/
#define TIMER_1_OFF()				(TCCR1B = 0x18);	/*!<Turn off R/C signal.*/

//Timer 2 overflow interrupt enable/disable
#define TIMER2_OVF_INT_ENABLE()		(TIMSK |= (1<<TOIE2))	/*!<Enable TIMER2 overflow interrupt.*/
#define TIMER2_OVF_INT_DISABLE()	(TIMSK &= ~(1<<TOIE2))	/*!<Disable TIMER2 overflow interrupt.*/

//Encoder signals interrupts enable/disable
#define ENCODER_INTERRUPT_ENABLE()	(GICR |= (0xC0))	/*!<Enable encoders interrupt.*/
#define ENCODER_INTERRUPT_DISABLE()	(GICR &= ~(0xC0))	/*!<Disble encoders interrupt.*/

//Safety feedback loop
#define SRF08_SAFETY_RANGE 			(10)	/*!<Safety range in cm.*/

//Others
#define FALSE						(0)	/*!<True.*/
#define TRUE						(!FALSE) /*!<False.*/

/*!
* Timer 2 time intervals enum.
*/
typedef enum
{
	TIMER2_SEND_SRF08_COMMAND = 0,
	TIMER2_READ_SRF08_DATA = 23,
	TIMER2_SPEED_REGULATORS = 24
		
} Timer2Intervals;

/*!
* UART Rx packet bytes enum.
*/
typedef enum
{
	COMMAND_IDENTIFIER,
	DATA1,
	DATA2,
	RX_CHECKSUM_BYTE,

	RX_PACKET_LENGTH

} RxPacketByte;

/*!
* UART Tx packet bytes enum.
*/
typedef enum
{
	TX_CHECKSUM_BYTE = 11,	
	
	TX_PACKET_LENGTH

} TxPacketByte;

/*!
* Communication packet identifier bytes enum.
*/
typedef enum
{
	//Odometry headers
	ODOMETRY_SET_X = 0xA0,
	ODOMETRY_SET_Y,
	ODOMETRY_SET_PHI,
	ODOMETRY_RESET_ALL,

	//Motors control
	MOTORS_RIGHT_MOMENTUM = 0xC0,
	MOTORS_LEFT_MOMENTUM,
	MOTORS_RIGHT_SPEED_CMPS,
	MOTORS_LEFT_SPEED_CMPS,
	MOTORS_BOTH_MOMENTUM,
	MOTORS_BOTH_SPEED_IMPPS,
	MOTORS_WALL_FOLLOWING,
	MOTORS_POSITION_REGULATOR,

	//Regulators
	REGULATORS_X_DESIRED = 0xD0,
	REGULATORS_Y_DESIRED,
	REGULATORS_GAMMA,
	REGULATORS_EPSILON,
	REGULATORS_ANGLE_GAIN,
	REGULATORS_POSITION_GAIN,
	REGULATORS_SPEED,

	//Configuration
	CONFIGURATION_RIGHT_WHEEL_CIRCUM = 0xE0,
	CONFIGURATION_LEFT_WHEEL_CIRCUM,
	CONFIGURATION_TRACK,
	CONFIGURATION_IMP_PER_ROUND,
	CONFIGURATION_SRF08_SAFETY_ADDRESSES,
	CONFIGURATION_MAX_ACCELERATION,
	CONFIGURATION_KP,
	CONFIGURATION_KD,
	CONFIGURATION_KI,
	CONFIGURATION_SRF08_ADDRESSES,
	CONFIGURATION_REG_ERR_THRESH,
	CONFIGURATION_OMEGA_0,
	CONFIGURATION_L,
	CONFIGURATION_KSI,
	CONFIGURATION_OMEGA_THRESH,
	CONFIGURATION_REAR_CORRECTION,

	//Status data requests
	SEND_ODOMETRY = 0xF0,
	SEND_CONFIG_1,
	SEND_CONFIG_2,
	SEND_SRF08,
	SEND_REGULATORS

} PacketHeaders;

/*!
* Configuration structure.
*/
typedef struct 
{
	uint8_t SRF08_Front, /*!<Address of front SRF08 sensor.*/ SRF08_Rear;	/*!<Address of rear SRF08 sensors.*/
	uint8_t ImpPerRoundR, /*!<Impulses per round of right wheel speed encoder (divided by 2 to fit uint8_t size when sampling STEP on both edges).*/ ImpPerRoundL; /*!<Impulses per round of left wheel speed encoder (divided by 2 to fit uint8_t size when sampling STEP on both edges).*/ 
	uint16_t CircumR, /*!<Right wheel circumference in cm.*/ CircumL;	/*!<Left wheel circumference in cm.*/	
	uint16_t Track;	/*!<Wheels track in cm.*/			
	uint8_t MaxAcc; /*!<max. acceleration (0 - 10 recommended).*/
	uint8_t Kp, /*!<Proportional coefficient of the PSD speed regulators (multiplied by 10!!!).*/ Ki, /*!<Integral coefficient of the PSD speed regulators (multiplied by 10!!!).*/ Kd; /*!<Derivative coefficient of the PSD speed regulators (multiplied by 10!!!).*/
	uint8_t RegErrorFilter; /*!<Lower threshold of the regulator error.*/
	uint8_t Omega0, /*!<Natural frequency (multiplied by 10!!).*/ L, /*!<Distance between SRF08 sensors/2 (in cm).*/ Ksi;	 /*!<Ksi (damping factor, multiplied by 10!!).*/
	uint8_t OmegaThresh;	/*!<Threshold for angular speed.*/
	uint8_t SRF08_RearCorrection;		/*!<SRF08 rear sensor distance correction.*/
	uint8_t RightWheelIncrement, /*!<Track increment (mm per pulse) of right wheel.*/ LeftWheelIncrement; /*!<Track increment (mm per pulse) of left wheel.*/
	uint8_t SRF08_SafetyFirst, /*!<Address of SRF08 front safety sensors.*/ SRF08_SafetySecond;	/*!<Address of SRF08 rear safety sensors.*/
	uint8_t RegGamma, /*!<Position regulator gamma (x10!!!).*/ RegEpsilon, /*!<Position regulator epsilon.*/ RegAngleGain, /*!<Position regulator angle gain (x10!!!).*/ RegPositionGain, /*!<Position regulator distance gain (x10!!!).*/ RegSpeed; /*!<Position regulator constant forwars speed (in cm/s, if allowed).*/
} t_ConfigStruct;

/*!
* ISRs shared variables structure
*/
typedef struct
{
	volatile uint8_t UARTRxIndex,/*!<Index in UARTReceivedData[] array.*/ Timer0Prescaler;	/*!<Software prescaler for TIMER0.*/
	volatile uint8_t UARTWatchdog;	/*!<UART watchdog counter.*/
	volatile int16_t BufferOdoL, /*!<Counts impulses from left wheel speed sensor for calculation of odometry.*/ BufferOdoR; /*!<Counts impulses from right wheel speed sensor for calculation of odometry.*/
	volatile int16_t BufferSpeedL, /*!<Counts impulses from left wheel speed sensor for calculation of current wheel speed.*/ BufferSpeedR; /*!<Counts impulses from right wheel speed sensor for calculation of current wheel speed.*/
	volatile uint8_t MomSpeedR, /*!<Desired momentum (speed) of the motor.*/ MomSpeedL;	/*!<Desired momentum (speed) of the motor.*/
	volatile uint8_t EnableSpRegR, /*!<Determines whether speed regulator of the motor is enabled.*/ EnableSpRegL; /*!<Determines whether speed regulator of the motor is enabled.*/
	volatile uint8_t EnableWallFollowing; /*!<Determines whether wall-following is enabled.*/
	volatile int16_t ActualRPML, /*!<Actual RPM of left wheel (impulses per 50 ms).*/ ActualRPMR; /*!<Actual RPM of right wheel (impulses per 50 ms).*/
	volatile int16_t RegIntegratorR, /*!<Right integrator value.*/RegIntegratorL;	/*!<Left integrator value.*/
	volatile uint8_t SRF08_DistanceFront, /*!<Distance measured by front SRF08 sensor.*/ SRF08_DistanceRear; /*!<Distance measured by rear SRF08 sensor.*/
	volatile uint8_t y0_des, /*!<Desired value of y0 (distance from the tracked wall).*/ V_des;  /*!<Desired speed (cm/s).*/
	volatile int16_t Ky, /*!<Position loop gain.*/ Kfi; /*!<angular speed loop gain.*/
	volatile int16_t X, /*!<Odometry X [mm].*/ Y, /*!<Odometry Y [mm].*/ Phi; /*!<Odometry Phi [mRad].*/
	volatile uint8_t EnablePositionRegulator;	/*!<Determines whether position regulator is enabled.*/
	volatile int16_t Xdes, /*!<Desired X coordinate for the position regulator [mm].*/ Ydes; /*!<Desired Y coordinate for the position regulator [mm].*/
	volatile int16_t TotalImpulsesR, /*!<Total number of impulses captured by right encoder.*/ TotalImpulsesL; /*!<Total number of impulses captured by left encoder.*/
	volatile int16_t RegulateAngleOnly;	/*!<If != 0, position regulator regulates only angle specified by this variable's value.*/
} t_ISRsSharedStruct;


#endif //_DEFINES
/*! @} */
