#include <stddef.h>
#include "stm32f2xx.h"
/*#include "stm32f2xx_gpio.h"
#include "stm32f2xx_rcc.h"*/
void configureClock()
{
	ErrorStatus HSEStartUpStatus;
	RCC_DeInit(); //reset

	RCC_HSEConfig(RCC_HSE_ON); //turn on external oscillator

	HSEStartUpStatus = RCC_WaitForHSEStartUp(); //check if HSE ready, timeout if not ready

	if(HSEStartUpStatus == SUCCESS) //if startup was correct
	{

		FLASH_PrefetchBufferCmd(ENABLE); // Enable Prefetch Buffer (when AHB != 1, enable to be sure...)
		FLASH_SetLatency(FLASH_Latency_2); //2 wait state, because clock between 48Mhz and 72Mhz
		RCC_HCLKConfig(RCC_SYSCLK_Div1); //HCLK(AHB)-Clock = SYSCLK (I think peripheral clock)
		RCC_PCLK2Config(RCC_HCLK_Div1); //PCLK2 = HCLK (for APB1 devices, high speed APB)
		RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1 = HCLK/2 (for APB2 devices, low speed APB)
//		RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //PLL Source HSE_Clock, Multiplier 9x (72Mhz)

		//PLL configuration
			//HSE -> PLL input divider (Result must be between 1 and 2 MHz)
			#define MY_PLL_M	25		//1 MHz

			//PLL multiplication factor (to reach a value between 192 and 432 MHz)
			#define MY_PLL_N	240		//240 MHz

			//PLL divider for SYSCLK (reach a value between 1...120 MHz)
			#define MY_PLL_P	2		//120 MHz

			//divider for USB OTG FS, SDIO and RNG (48 MHz needed here)
			#define MY_PLL_Q	5		//48 MHz


			RCC_PLLConfig(RCC_PLLSource_HSE, MY_PLL_M, MY_PLL_N, MY_PLL_P, MY_PLL_Q);

		RCC_PLLCmd(ENABLE); //enable PLL

		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //wait until PLL is ready

		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //PLL as System Clock Source

		while(RCC_GetSYSCLKSource() != 0x08); //wait until PLL is used as system clock source
	}
	return;
}

void configureUart()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
		//'RCC_APB2Periph_AFIO' undeclared (first use in this function)
		//Auch sonst gibt es nichts, was AFIO o.ä. heisst

	GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_USART2);
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_USART2);

	GPIO_StructInit(&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOD, &GPIO_InitStructure);

	GPIO_StructInit(&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOD, &GPIO_InitStructure);

	USART_StructInit(&USART_InitStructure);
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	//8 Bits
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_Init(USART2, &USART_InitStructure);

	USART_Cmd(USART2, ENABLE);


/*	USART_DeInit(USART2);

*/
}
void delayLoop() {
	volatile uint32_t delayCount = 1000000; // volatile, um "Wegoptimieren" zu vermeinden
                                                //(http://en.wikipedia.org/wiki/Volatile_variable)
	while (delayCount > 0) {
		delayCount--;
	}
}

int main(void)
{
	configureClock();

	configureUart();


	//done by configureUart()
	//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

	//blinky conf
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_StructInit(&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_13;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
	GPIO_Init(GPIOD, &GPIO_InitStructure);




	/*TIM_DeInit(TIM6);
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);

	TIM_TimeBaseInitStruct.TIM_Prescaler = (uint16_t) 100000;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;*/
	while (1)
	{
		USART_SendData(USART2, (uint16_t) 0x49);
		GPIO_ToggleBits(GPIOD, GPIO_Pin_13);
		//GPIO_ToggleBits(GPIOD, GPIO_Pin_5);
		delayLoop();delayLoop();delayLoop();delayLoop();

	}
	return 0;
}
