/**
 ******************************************************************************
 * @file           : main.c
 * @author         : Auto-generated by STM32CubeIDE
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
 * All rights reserved.</center></h2>
 *
 * This software component is licensed by ST under BSD 3-Clause license,
 * the "License"; You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                        opensource.org/licenses/BSD-3-Clause
 *
 ******************************************************************************
 */


#if !defined(__SOFT_FP__) && defined(__ARM_FP)
  #warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
#endif

#include "stm32l073xx.h"

void test(uint32_t cas)
{
	for(uint32_t x = 0U; x < cas; x++);

	// zapne USART2/4
	//RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
	RCC->APB1ENR |= RCC_APB1ENR_USART4EN;

	for(uint32_t x = 0U; x < cas; x++);

	// vypne USART2/4
	//RCC->APB1ENR &= ~RCC_APB1ENR_USART2EN;
	RCC->APB1ENR &= ~RCC_APB1ENR_USART4EN;
}

void testMsi(void)
{
	test(400000U);

	// nastavi MSI na 4,194 MHz
	RCC->ICSCR = ((6 << RCC_ICSCR_MSIRANGE_Pos) | (RCC->ICSCR & ~RCC_ICSCR_MSIRANGE_Msk));

	test(800000U);
}

void nastavHsi()
{
	// zapne interni vysokorychlostni oscilator
	RCC->CR |= RCC_CR_HSION;

	// cekej, dokud HSI neni pripraveny
	while (!(RCC->CR & RCC_CR_HSIRDY));

	// nastavi HSI jako zdroj hodinoveho signalu
	RCC->CFGR |= RCC_CFGR_SW_HSI;

	// cekej, dokud neni zdroj prepnuty
	while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI);

	// vypne interni vicerychlostni oscilator
	RCC->CR &= ~RCC_CR_MSION;
}

void testHsi(void)
{
	// nastavi delicku /4 -> 4 MHz
	RCC->CFGR |= RCC_CFGR_HPRE_DIV4;

	nastavHsi();

	test(800000U);

	// nastavi delicku /2 -> 8 MHz
	RCC->CFGR = (RCC_CFGR_HPRE_DIV2 | (RCC->CFGR & ~RCC_CFGR_HPRE_Msk));

	test(1600000U);

	// nastavi napetovou uroven 1
	PWR->CR = (1 << PWR_CR_VOS_Pos);

	// nastavi delicku /1 -> 16 MHz
	RCC->CFGR &= ~RCC_CFGR_HPRE_Msk;

	test(3200000U);
}

void nastavPll()
{
	nastavHsi();

	// nastavi napetovou uroven 1
	PWR->CR = (1 << PWR_CR_VOS_Pos);

	// zapne cekaci stav
	FLASH->ACR |= FLASH_ACR_LATENCY;

	// PLL nasobi 4x
	RCC->CFGR |= RCC_CFGR_PLLMUL4;

	// PLL deli 2x
	RCC->CFGR |= RCC_CFGR_PLLDIV2;

	// Zapne PLL
	RCC->CR |= RCC_CR_PLLON;

	// cekej, dokud neni PLL pripraven
	while ((RCC->CR & RCC_CR_PLLRDY) != RCC_CR_PLLRDY);

	// nastavi PLL jako zdroj hodinoveho signalu
	RCC->CFGR |= RCC_CFGR_SW_PLL;

	// cekej, dokud neni zdroj prepnuty
	while ((RCC->CFGR & RCC_CFGR_SWS_PLL) != RCC_CFGR_SWS_PLL);
}

void testPll(void)
{
	nastavPll();

	test(4500000U);
}

int main(void)
{
	//testMsi();

	//testHsi();

	testPll();
}
