/**
 ******************************************************************************
 * @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"

#define VELIKOST_DAT 1000
uint32_t data1[VELIKOST_DAT];

void prenosDat(uint32_t pocetIteraci)
{
	uint32_t data2[VELIKOST_DAT];

	for(uint32_t x = 0U; x < pocetIteraci; x++)
	{
		for(uint32_t y = 0U; y < VELIKOST_DAT; y++)
		{
			data1[y] = (data2[y])++;
		}
	}
}

void zapniLPProvozniRezim()
{
	// prepne regulator napeti do usporneho rezimu
	// musi byt prvni
	PWR->CR |= PWR_CR_LPSDSR;

	// prepne kontroler do nizkoprikonoveho provozniho rezimu
	PWR->CR |= PWR_CR_LPRUN;
}

void zapniProvozniRezim()
{
	// prepne kontroler do provozniho rezimu
	// musi byt prvni
	PWR->CR &= ~PWR_CR_LPRUN;

	// prepne regulator napeti do standardniho rezimu
	PWR->CR &= ~PWR_CR_LPSDSR;
}

void nastavUart(void)
{
	// zapne hodinovy signal pro port A
	RCC->IOPENR |= RCC_IOPENR_IOPAEN;

	// vynuluje nastaveni rezimu PA2 (vstupni rezim)
	GPIOA->MODER &= ~GPIO_MODER_MODE2;

	// nastavi  PA2 do alternativniho rezimu
	GPIOA->MODER |= GPIO_MODER_MODE2_1;

	// nastavi pinu PA2 alternativni rezim 4 - UART
	GPIOA->AFR[0] |= (4U << GPIO_AFRL_AFSEL2_Pos);

	// nastavi zdroj USART2 -> HSI
	//RCC->CCIPR |=  RCC_CCIPR_USART2SEL_1;

	// zapne hodinovy signal pro USART2
	RCC->APB1ENR |= RCC_APB1ENR_USART2EN;

	// 2 * 131 KHz / 28 = 9357 (duvod vypoctu v manualu)
	USART2->BRR = 22U;

	// povoli USART, prevzorkovani 8x, a odesilani dat
	USART2->CR1 |= (USART_CR1_UE | USART_CR1_OVER8 | USART_CR1_TE);
}


void posliData(uint32_t pocetIteraci)
{
	for(uint32_t x = 0U; x < pocetIteraci; x++)
	{
		USART2->TDR = 'x';

		// cekej, dokud se znak neodesle
		while((USART2->ISR & USART_ISR_TXE) != USART_ISR_TXE);
	}
}


int main(void)
{
	// zapne periferii nastaveni napajeni
	RCC->APB1ENR |= RCC_APB1ENR_PWREN;

	// zapne HSI
	//RCC->CR |= RCC_CR_HSION;

	// reset nastaveni rychlosti MSI
	RCC->ICSCR &= ~RCC_ICSCR_MSIRANGE_Msk;

	// nastavi MSI rychlost 1 -> 131 KHz
	RCC->ICSCR |= ((1 << RCC_ICSCR_MSIRANGE_Pos) & RCC_ICSCR_MSIRANGE_Msk);

	PWR->CR = (3 << PWR_CR_VOS_Pos);

	prenosDat(10);

	nastavUart();

	RCC->APB1ENR |= (RCC_APB1ENR_TIM2EN | RCC_APB1ENR_SPI2EN | RCC_APB1ENR_I2C1EN | RCC_APB1ENR_I2C2EN | RCC_APB1ENR_LPTIM1EN | RCC_APB1ENR_TIM3EN);

	prenosDat(10);

	//posliData(5000);

	zapniLPProvozniRezim();

	prenosDat(10);

	/*posliData(5000);

	zapniProvozniRezim();

	prenosDat(10);*/

	while(1);
}
