/**
**************************************************************************************************
* @file		hardwareDescription.h
* @author		Kerem Yollu & Edwin Koch
* @date		19.12.2021
* @version	1.0
************************************************************************************************** 
* @brief		This file contains all hardware specific definitions for STM32F042K6
* 
* **Detailed Description :**
* This Header file contains all the registers and their bit manipulation options. 
* All the extra Tables created here are to somplifly the main codes readability 
*
* @todo 
*	- 19.12.2021 : implement until it runs :) 
**************************************************************************************************
*/

#ifndef _hardwareDescription_H_
#define _hardwareDescription_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "stm32f042x6.h"
#include <stdint.h>

#define PACKAGE_LQFP32 1

#define MAX_USART_CHANNEL_COUNT 2
#define MAX_I2C_CHANNEL_COUNT 1
#define MAX_SPI_CHANNEL_COUNT 2
#define MAX_I2S_CHANNEL_COUNT 2
#define MAX_CAN_CHANNEL_COUNT 1
#define MAX_TIMER_CHANNEL_COUNT 6

#define MAX_N_PORTS_COUNT	3
#define MAX_PORT_PINS_COUNT	16
#define MAX_N_PIN_ALT_FUNC	8

#define MAX_PORT_A_PIN_NO	15
#define MAX_PORT_B_PIN_NO	15
#define MAX_PORT_F_PIN_NO	1

/*! Pin number typedef enum. It contains all the available pins */
typedef enum 
{
//  NAME  = BASE ADDR   | PORT | PIN NO
	pinA0 =  0x00 | 0,	/*!< Port: A Pin: 0  ->  Port A Mask | Pin Mask */
	pinA1 =  0x00 | 1,	/*!< Port: A Pin: 1  ->  Port A Mask | Pin Mask */
	pinA2 =  0x00 | 2,	/*!< Port: A Pin: 2  ->  Port A Mask | Pin Mask */
	pinA3 =  0x00 | 3,	/*!< Port: A Pin: 3  ->  Port A Mask | Pin Mask */
	pinA4 =  0x00 | 4,	/*!< Port: A Pin: 4  ->  Port A Mask | Pin Mask */
	pinA5 =  0x00 | 5,	/*!< Port: A Pin: 5  ->  Port A Mask | Pin Mask */
	pinA6 =  0x00 | 6,	/*!< Port: A Pin: 6  ->  Port A Mask | Pin Mask */
	pinA7 =  0x00 | 7,	/*!< Port: A Pin: 7  ->  Port A Mask | Pin Mask */
	pinA8 =  0x00 | 8,	/*!< Port: A Pin: 8  ->  Port A Mask | Pin Mask */
	pinA9 =  0x00 | 9,	/*!< Port: A Pin: 9  ->  Port A Mask | Pin Mask */
	pinA10 = 0x00 | 10,	/*!< Port: A Pin: 10 ->  Port A Mask | Pin Mask */
	pinA11 = 0x00 | 11,	/*!< Port: A Pin: 11 ->  Port A Mask | Pin Mask */
	pinA12 = 0x00 | 12,	/*!< Port: A Pin: 12 ->  Port A Mask | Pin Mask */
	pinA13 = 0x00 | 13,	/*!< Port: A Pin: 13 ->  Port A Mask | Pin Mask */
	pinA14 = 0x00 | 14,	/*!< Port: A Pin: 14 ->  Port A Mask | Pin Mask */
	pinA15 = 0x00 | 15,	/*!< Port: A Pin: 15 ->  Port A Mask | Pin Mask */

	pinB0 =  0x10 | 0,	/*!< Port: B Pin: 0  ->  Port B Mask | Pin Mask */
	pinB1 =  0x10 | 1,	/*!< Port: B Pin: 1  ->  Port B Mask | Pin Mask */
	pinB3 =  0x10 | 3,	/*!< Port: B Pin: 3  ->  Port B Mask | Pin Mask */
	pinB4 =  0x10 | 4,	/*!< Port: B Pin: 4  ->  Port B Mask | Pin Mask */
	pinB5 =  0x10 | 5,	/*!< Port: B Pin: 5  ->  Port B Mask | Pin Mask */
	pinB6 =  0x10 | 6,	/*!< Port: B Pin: 6  ->  Port B Mask | Pin Mask */
	pinB7 =  0x10 | 7,	/*!< Port: B Pin: 7  ->  Port B Mask | Pin Mask */
	pinB8 =  0x10 | 8,	/*!< Port: B Pin: 8  ->  Port B Mask | Pin Mask */
             
	pinF0 =  0x20 | 0,	/*!< Port: F Pin: 0  ->  Port F Mask | Pin Mask */
	pinF1 =  0x20 | 1	/*!< Port: F Pin: 1  ->  Port F Mask | Pin Mask */
}pinNo_t;    

/*!List of all possible port base addresses. This is used for the funcionality of of pin.h*/
static const  uint32_t portBase_Addr_List[MAX_N_PORTS_COUNT] = {
	GPIOA_BASE,	//!< Base address Port A 
	GPIOB_BASE, //!< Base address Port B
	GPIOF_BASE	//!< Base address Port F
};

/*! This is a bitmap list of all possible alternative functions for each pin.
 *	1means that there is an alternative function available and 0 for none. Tis is used
 *	for the functionality in pin.h
 *	*/             
static const uint8_t altFunc_List[MAX_N_PORTS_COUNT][MAX_PORT_PINS_COUNT] = {
	{	// PORT A
		0b01110000, //PA0 
		0b11110000, //PA1
		0b01110000, //PA2
		0b01110000, //PA3	
		0b11111000, //PA4	
		0b11110000, //PA5 
		0b11110110, //PA6
		0b11111110, //PA7
		0b11111000, //PA8
		0b01111100, //PA9
		0b11111000, //PA10
		0b11111100, //PA11
		0b11111100, //PA12
		0b11100000, //PA13
		0b11000000, //PA14
		0b11110100	//PA15
	},
	{	// PORT B
		0b11110000, //PB0  
		0b11110000, //PB1  
		0b00010000, //PB2  
		0b11110000, //PB3  
		0b11110100, //PB4  
		0b11110000, //PB5  
		0b11110000, //PB6  
		0b11110000, //PB7  
		0b11111000, //PB8  
		0b11111100, //PB9  
		0b11110100, //PB10 
		0b11100000, //PB11 
		0b11100000, //PB12
		0b10100100, //PB13
		0b10100100, //PB14
		0b10100000	//PB15
	},
	{	// PORT F
		0b11000000, //PF0 
		0b01000000, //PF1 
		0b00000000, //N.A 
		0b00000000, //N.A 
		0b00000000, //N.A 
		0b00000000, //N.A 
		0b00000000, //N.A 
		0b00000000, //N.A 
		0b00000000, //N.A 
		0b00000000, //N.A 
		0b00000000, //N.A
		0b00000000, //N.A
		0b00000000, //N.A
		0b00000000, //N.A
		0b00000000, //N.A
		0b00000000	//N.A
	}	
};


/*!
 * Enum for awailable timer DS Page: 12 (block diagaram) The order of the enums is very important
 * and should not be changed as it is used ofr table indexing 
 * */
typedef enum {
	timer_1,	/*!< Advanced control 16-bit timer with PWM capability RM Page: 320 */
	timer_2,	/*!< General purpose 32-bit timer RM Page: 393 */
	timer_3,	/*!< General purpose 16-bit timer RM Page: 393 */
	timer_14,	/*!< General purpose 16-bit timer RM Page: 459 */
	timer_16,	/*!< General purpose 16-bit timer RM Page: 480 */
	timer_17	/*!< General purpose 16-bit timer RM Page: 480 */
} timerNo_t;

/*! 
 * Enum for awailable clok sources RM Page: 95 
 * */

typedef enum { 
	CLK_HSI,	/*!< High speed internal */ 
	CLK_HSE,	/*!< High speed external */
	CLK_LSI,	/*!< Low speed internal */
	CLK_LSE		/*!< Low speed External */
}clkSources_t;

/*!
 *	Timer base addresslist of all available timers
 * */
static const uint32_t timerBase_Addr_List[MAX_TIMER_CHANNEL_COUNT] = {
	TIM1_BASE,	/*!< Timer 1 Base Address */ 
	TIM2_BASE,	/*!< Timer 2 Base Address */
	TIM3_BASE,	/*!< Timer 3 Base Address */
	TIM14_BASE, /*!< Timer 14 Base Address */
	TIM16_BASE, /*!< Timer 16 Base Address */
	TIM17_BASE	/*!< Timer 17 Base Address */
};

/*!
 *	RCC clock enabcke bit position for the given register
 * */
static const uint8_t timerBus_En_bitPos[MAX_TIMER_CHANNEL_COUNT] = {
	RCC_APB2ENR_TIM1EN_Pos,
	RCC_APB1ENR_TIM2EN_Pos,
	RCC_APB1ENR_TIM3EN_Pos,
	RCC_APB1ENR_TIM14EN_Pos,
	RCC_APB2ENR_TIM16EN_Pos,
	RCC_APB2ENR_TIM17EN_Pos
};

/*!
 *	RCC timer Reset Bit Position list
 * */
static const uint8_t timerBus_Rst_bitPos[MAX_TIMER_CHANNEL_COUNT] = {
	RCC_APB2RSTR_TIM1RST_Pos,
	RCC_APB1RSTR_TIM2RST_Pos,
	RCC_APB1RSTR_TIM3RST_Pos,
	RCC_APB1RSTR_TIM14RST_Pos,
	RCC_APB2RSTR_TIM16RST_Pos,
	RCC_APB2RSTR_TIM17RST_Pos
};

/*!
 *	RCC Bus number index list connected to the timer 
 * */
static const uint8_t timerBus_No[MAX_TIMER_CHANNEL_COUNT] = {
	2, /*!< timer 1 is connected to bus 2 */
	1, /*!< timer 2 is connected to bus 1 */
	1, /*!< timer 3 is connected to bus 1 */
	1, /*!< timer 14 is connected to bus 1 */
	2, /*!< timer 16 is connected to bus 2 */
	2  /*!< timer 17 is connected to bus 2 */
};

/*! 
 * Timer Prescaler resolution list TO BE DELETED IF NOT NEEDED
 * */
static const  uint32_t timerRes_Prescaler[MAX_TIMER_CHANNEL_COUNT] = {
	0xFFFF, /*!< Timer 1 Prescaler Max Value */ 
	0xFFFF, /*!< Timer 2 Prescaler Max Value */ 
	0xFFFF, /*!< Timer 3 Prescaler Max Value */ 
	0xFFFF, /*!< Timer 14 Prescaler Max Value */ 
	0xFFFF, /*!< Timer 16 Prescaler Max Value */ 
	0xFFFF, /*!< Timer 17 Prescaler Max Value */ 
};

/*!
 *	RCC Bus number index list connected to the SPI 
 * */
static const uint8_t spiBus_No[MAX_SPI_CHANNEL_COUNT] = {
	2, /*!< SPI 1 is connected to bus 2 */
	1  /*!< SPI 2 is connected to bus 1 */
};

/*!
 *	RCC SPI clock enable bit position for the given register
 * 
 */
static const uint8_t spiBus_En_bitPos[MAX_SPI_CHANNEL_COUNT] = {
	RCC_APB2ENR_SPI1EN_Pos,
	RCC_APB1ENR_SPI2EN_Pos
};

/*!
 *	RCC SPI Reset Bit Position list
 * */
static const uint8_t spiBus_Rst_bitPos[MAX_SPI_CHANNEL_COUNT] = {
	RCC_APB2RSTR_SPI1RST_Pos,
	RCC_APB1RSTR_SPI2RST_Pos
};

/**
 * Enumof available spi hardware channels
 */
typedef enum{
	SPI_CH_1,
	SPI_CH_2
} spiCH_t;
/**
 * SPI base address list
 */
static const uint32_t spiBase_Addr_List[MAX_SPI_CHANNEL_COUNT] =  {
	SPI1_BASE,
	SPI2_BASE
};

#ifdef __cplusplus
}
#endif

#endif // _hardwareDescription_H_