#include "deviceSetup.h"
#include "stm32f042x6.h"


#define SET_BIT(REG, BIT)     ((REG) |= (BIT))
#define CLEAR_BIT(REG, BIT)   ((REG) &= ~(BIT))
#define READ_BIT(REG, BIT)    ((REG) & (BIT))
#define CLEAR_REG(REG)        ((REG) = (0x0))
#define WRITE_REG(REG, VAL)   ((REG) = (VAL))
#define READ_REG(REG)         ((REG))
#define MODIFY_REG(REG, CLEARMASK, SETMASK)  WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
//													FLASH->ACR = (((FLASH->ACR) & (~(FLASH_ACR_LATENCY))) | 0)					 	
#define SYS_CLK 8000000


void setupInit()
{
	setupBus();
	setupMemory();
	setupClock();
	setupPower();
	delayInitMs(SYS_CLK, 1000);
}

void setupClock()
{
	uint8_t check = 1;
	/*Sets the clock source to internal clock*/
	RCC->CR |= RCC_CR_HSION;

	/* Wait till HSI is ready */
	while(check)
	{
		if(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == (RCC_CR_HSIRDY))
		{
			check = 0;
		}
	}

	/**
	  * @brief  Set HSI Calibration trimming
	  * @note Default value is 16, which, when added to the HSICAL value,
	  * @param  Value between Min_Data = 0x00 and Max_Data = 0x1F
	  */
	MODIFY_REG(RCC->CR, RCC_CR_HSITRIM_Msk, 16 << RCC_CR_HSITRIM_Pos) ;
	MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_CFGR_HPRE_DIV1);
	MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE, RCC_CFGR_PPRE_DIV1);
	MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_HSI);

	/* Wait till System clock is ready */
	while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI){}
}	

void setupBus()
{
  volatile uint32_t tmpreg;
  /*Bit 0 SYSCFGCOMPEN: SYSCFG & COMP clock enable*/
  SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN);
  /* Delay after an RCC peripheral clock enabling */
  tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN);

  /*Bit 28 PWREN: Power interface clock enable*/
  SET_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN);
  /* Delay after an RCC peripheral clock enabling */
  tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN);
  
  (void)tmpreg;

}	

void setupPower()
{

}

void setupMemory()
{
	/* Bits 2:0 LATENCY[2:0]: Latency
	 * These bits represent the ratio of the SYSCLK (system clock) period to the Flash access time.
	 * 000: Zero wait state, if SYSCLK ≤ 24 MHz
	 * 001: One wait state, if 24 MHz < SYSCLK ≤ 48 MHz*/
	if(SYS_CLK <= 24000000)
	{
		FLASH->ACR = (((FLASH->ACR) & (~(FLASH_ACR_LATENCY_Msk))) | 0);					 	
		while( ((FLASH->ACR) & (FLASH_ACR_LATENCY_Msk)) != 0){}
	}
	else 
	{
		FLASH->ACR = (((FLASH->ACR) & (~(FLASH_ACR_LATENCY_Msk))) | 1);				 	
		while( ((FLASH->ACR) & (FLASH_ACR_LATENCY_Msk)) != 1){}
	}
}

void delayInitMs(uint32_t clk, uint32_t ticks)
{
  /* Configure the SysTick to have interrupt in 1ms time base */
  SysTick->LOAD  = (uint32_t)((clk / ticks) - 1UL);							/* set reload register */
  SysTick->VAL   = 0UL;														/* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;	/* Enable the Systick Timer */
}