#include "stm32f0xx.h"
#include <stdbool.h>
#include <stdio.h>
#include "main.h"

static char text[255];
RCC_ClocksTypeDef Clocks;

void init(void) {
	SystemInit();

	// Setup the PLL - found some code on the net and adopted it (silly bits ...)
	RCC->CR &= ~(1<<24);  // disable pll first
	while( (RCC->CR & (1<<25))); // wait for PLL ready to be cleared
	// set PLL multiplier to 12 (yielding 48MHz)
	// inserted into Flash memory interface
	FLASH->ACR |= (1<<0);
	FLASH->ACR &=~((1<<2) | (1<<1));

	// Turn on FLASH prefetch buffer
	FLASH->ACR |= (1<<4);
	RCC->CFGR &= ~((1<<21) | (1<<20) | (1<<19) | (1<<18));
	RCC->CFGR |= ((1<<21) | (1<<19) );

	// Need to limit ADC clock to below 14MHz so will change ADC prescaler to 4
	RCC->CFGR |= (1<<14);

	// and turn the PLL back on again
	RCC->CR |= (1<<24);
	// set PLL as system clock source
	RCC->CFGR |= (1<<1);



	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStruct;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

	// LED: Configure PA0 and PA1 in output pushpull mode
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	// UART1: Configure PA9 and PA10
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);

	USART_InitStruct.USART_BaudRate = 57600; // the baudrate is set to the value we passed into this init function
	USART_InitStruct.USART_WordLength = USART_WordLength_8b; // we want the data frame size to be 8 bits (standard)
	USART_InitStruct.USART_StopBits = USART_StopBits_1; // we want 1 stop bit (standard)
	USART_InitStruct.USART_Parity = USART_Parity_No; // we don't want a parity bit (standard)
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // we don't want flow control (standard)
	USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // we want to enable the transmitter and the receiver
	USART_Init(USART1, &USART_InitStruct);

	// finally this enables the complete USART1 peripheral
	USART_Cmd(USART1, ENABLE);

	RCC_GetClocksFreq(&Clocks);
}

int main (void) {
	init();

	sprintf(text, "STM32F030-Test begins.\r\nHCLK is %d MHz, PCLK %d MHz, System %d MHz.\n", (Clocks.HCLK_Frequency/1000000), (Clocks.PCLK_Frequency/1000000), (Clocks.SYSCLK_Frequency/1000000));
	uart_tx(text);


	GPIOA->BRR = GPIO_Pin_0;  // Set PA0 to GND

	uint32_t my_counter = 0;
	int step = 10;
	uint32_t border=10000;
	while (1) {
		my_counter += step;
		if ((my_counter == border) | (my_counter==0)) step = -step;
		GPIOA->BSRR = GPIO_Pin_1;  // Set PA1 HIGH  (LED on)
		Delay(my_counter);
		GPIOA->BRR = GPIO_Pin_1;  // Set PA1 to GND (LED off)
		Delay(border-my_counter);
	}
}


void uart_tx(char *out) {
	while (*out)
	{
		while(!(USART1->ISR & USART_FLAG_TXE))
		{ // Nothing, really.;
		}
		USART1->TDR = *out++;
	}
}


void Delay(__IO uint32_t nCount) {
  while(nCount--) {
  }
}
