/**
  **************************************************************************************************
  * @file		pin.h
  * @author		Kerem Yollu & Edwin Koch
  * @date		01.11.2021
  * @version	1.0
  ************************************************************************************************** 
  * @brief		pin functionalities description and implementation template
  * 
  * **Detailed Description :**
  * 
  * This header file for pin control is based on the most common configuation options
  * curenty awailable for modern hardware. 
  * Depending of the used Chip, some function may vary or be unawailable. 
  * Please take a minute to go and explore the according Chips pin.c file to see woh each function 
  * is implmented.  
  *
  * @todo 
  * - 01.11.2021 : Should we add a seprate header in the cls layer containing the pinNo_t ?
  *	- 01.11.2021 : Depending on request implment a pinLock() function
  **************************************************************************************************
*/

#ifndef _GPIO_H_
#define _GPIO_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

#ifdef ARM_MCU
#include "../stm32f042/Drivers/CMSIS/Device/ST/STM32F0xx/Include/stm32f042x6.h"
	/*! Enum of the awailable pins for this package */
	typedef enum 
	{
	//  NAME  = BASE ADDR   | PORT | PIN NO
		pinA0 = GPIOA_BASE  | 0x00 | 0, /*!< Port: A Pin: 0  -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA1 = GPIOA_BASE	| 0x00 | 1,	/*!< Port: A Pin: 1  -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA2 = GPIOA_BASE	| 0x00 | 2,	/*!< Port: A Pin: 2  -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA3 = GPIOA_BASE	| 0x00 | 3,	/*!< Port: A Pin: 3  -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA4 = GPIOA_BASE	| 0x00 | 4,	/*!< Port: A Pin: 4  -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA5 = GPIOA_BASE	| 0x00 | 5,	/*!< Port: A Pin: 5  -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA6 = GPIOA_BASE	| 0x00 | 6,	/*!< Port: A Pin: 6  -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA7 = GPIOA_BASE	| 0x00 | 7,	/*!< Port: A Pin: 7  -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA8 = GPIOA_BASE	| 0x00 | 8,	/*!< Port: A Pin: 8  -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA9 = GPIOA_BASE	| 0x00 | 9,	/*!< Port: A Pin: 9  -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA10 = GPIOA_BASE | 0x00 | 10,/*!< Port: A Pin: 10 -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA11 = GPIOA_BASE | 0x00 | 11,/*!< Port: A Pin: 11 -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA12 = GPIOA_BASE | 0x00 | 12,/*!< Port: A Pin: 12 -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA13 = GPIOA_BASE | 0x00 | 13,/*!< Port: A Pin: 13 -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA14 = GPIOA_BASE | 0x00 | 14,/*!< Port: A Pin: 14 -> GPIOA_BASE | Port A Mask | Pin Mask */
		pinA15 = GPIOA_BASE | 0x00 | 15,/*!< Port: A Pin: 15 -> GPIOA_BASE | Port A Mask | Pin Mask */

		pinB0 = GPIOB_BASE	| 0x10 | 0,	/*!< Port: B Pin: 0  -> GPIOB_BASE | Port B Mask | Pin Mask */
		pinB1 = GPIOB_BASE	| 0x10 | 1,	/*!< Port: B Pin: 1  -> GPIOB_BASE | Port B Mask | Pin Mask */
		pinB3 = GPIOB_BASE	| 0x10 | 3,	/*!< Port: B Pin: 3  -> GPIOB_BASE | Port B Mask | Pin Mask */
		pinB4 = GPIOB_BASE	| 0x10 | 4,	/*!< Port: B Pin: 4  -> GPIOB_BASE | Port B Mask | Pin Mask */
		pinB5 = GPIOB_BASE	| 0x10 | 5,	/*!< Port: B Pin: 5  -> GPIOB_BASE | Port B Mask | Pin Mask */
		pinB6 = GPIOB_BASE	| 0x10 | 6,	/*!< Port: B Pin: 6  -> GPIOB_BASE | Port B Mask | Pin Mask */
		pinB7 = GPIOB_BASE	| 0x10 | 7,	/*!< Port: B Pin: 7  -> GPIOB_BASE | Port B Mask | Pin Mask */
		pinB8 = GPIOB_BASE	| 0x10 | 8,	/*!< Port: B Pin: 8  -> GPIOB_BASE | Port B Mask | Pin Mask */

		pinF0 = GPIOF_BASE	| 0x20 | 0,	/*!< Port: F Pin: 0  -> GPIOF_BASE | Port F Mask | Pin Mask */
		pinF1 = GPIOF_BASE	| 0x20 | 1	/*!< Port: F Pin: 1  -> GPIOF_BASE | Port F Mask | Pin Mask */
	}pinNo_t;
#endif

#ifdef RASPBERRY
#endif

/*! Enum of possible Pin Modes */
typedef enum 
{
	def_mode,	/*!< Is the **default** mode */
	input,		/*!< Set pin as **Input** */
	output, 	/*!< Set pin as **Output** */
	analog, 	/*!< Set pin as **Analog** */
	alternate	/*!< Set pin as **Alternate** */
}pinMode_t;

/*! Enum of possible Outpout Stages */
typedef enum 
{
	def_stage,	/*!< Set ouput stage to **Default** */
	floating,	/*!< Set ouput stage to **Floating** */
	pushPull,	/*!< Set ouput stage to **Push Pull** */
	openDrain	/*!< Set ouput stage to **Open Drain** */
}pinStage_t;

/*! Enum for the internal Pull-Up/Down resistors */
typedef enum 
{
	def_res,	/*!< **Default** internal resistance */
	none,		/*!< **Disbales** internal resistance */
	pullUp,		/*!< Set internal resistance as **Pull-Up** */
	pullDown	/*!< Set internal resistance as **Pull-Down** */
}pinPullUpDown_t;

/*! Enum to set the pin's speed*/
typedef enum 
{
	def_speed,	/*!< set pin's spped to **Default** */
	slow,		/*!< set pin's speed to **Slow** */
	normal,		/*!< set pin's speed to **Normal** */ 
	fast,		/*!< set pin's speed to **Fast** */
	veryFast	/*!< set pin's speed to **Very Fast** */
}pinSpeed_t;

typedef enum 
{
	disabled,
	enabled 
}pinInterrupt_t;

typedef struct 
{
	pinMode_t md; 
	pinStage_t st;
	pinPullUpDown_t pud;
	pinSpeed_t sp;
	pinInterrupt_t intr; 
}pinConfiguration_t;


typedef enum 
{
	notValidMode,
	notValidOut,
	OutOfRange,
	NotDeclared, 
	NotReachable, 
	NoPullUpDown, 
	NotAnalog, 
	NotDigital, 
	TooFast, 
	Bocked, 
	AlreadyUsed,
	NotGpio
}pinErrors_t;

/** 
 * @brief Configuration function that will call all the necessary function for an sucessfull pin initialisation
 * @param pinNo_t mode_t 
 * @retval none
 */
void pinConfig(pinNo_t pinNo, pinMode_t mode, pinStage_t stage, pinPullUpDown_t resistance, pinSpeed_t speed); 

/**
 * @brief Modes to set the direction or function of the pin
 */
void pinSetMode(pinNo_t pinNo, pinMode_t mode);

/**
 * @brief Output Stage Push-Pull High-z ect...
 */
void pinSetOutputStage(pinNo_t pinNo, pinStage_t stage); 

/**
* @brief  Depending of the hardare it is able to select the speed of given pins
*/
void pinSetSpeed(pinNo_t pinNo, pinSpeed_t speed); 

/**
* @brief  If internal Pull-up or Pull-donws are wailable
*/
void pinSetPullUpDonw(pinNo_t pinNo, pinPullUpDown_t resistance); 

/**
* @brief  If pin is set as alternate this function will modify the pins functionality
* If pin isn't set as alternate this function will set the pin to alternate mode. 
*/
void pinSetAlternate(pinNo_t pinNo, uint16_t alternate); 

/**
* @brief  Reads the pin's current value 
*/
uint8_t pinRead(pinNo_t pinNo);

/**
* @brief  Toggles th pin's value
*/
void pinToggle(pinNo_t pinNo);

/**
* @brief  Sets the pin hihg or low.
*/
void pinWrite(pinNo_t pinNo, uint8_t state);

/**
* @brief  Initiates all the preriferals needed for the given pin
*/
void pinInit(pinNo_t pinNo);

/**
* @brief  Deactivates all the preriferals needed for the given pin
*/
void pinDeInit(pinNo_t pinNo);

/**
* @brief  Resets pin to default
*/
void pinReset(pinNo_t pinNo);

/**
* @brief  Will pirnt tthe rurrent devices pin status and their configrarion.
* Dependeing on the platform an the form of information printing.
*/
void pinHardwareInfo(pinNo_t pinNo);

/**
* @brief  Handles the given error and stops all further execution.
* Dependeing on the platfonr an the form of information printing.
*/
void pinThrowError(); 	

#ifdef __cplusplus
}
#endif

#endif // _GPIO_H_
