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

#include "stm32l073xx.h"

#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

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

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

	// nastavi  PA2 a PA3 do alternativniho rezimu
	GPIOA->MODER |= (GPIO_MODER_MODE2_1 | GPIO_MODER_MODE3_1);

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

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

	// 2097 MHz / 219 = 9575 Baud
	USART2->BRR = 219U;

	// povoli USARTa prijem dat
	USART2->CR1 |= (USART_CR1_UE | USART_CR1_TE);
}

void inkrementujZalohovaciRegistr()
{
	// povoli zapis do zalovacich registru
	PWR->CR |= PWR_CR_DBP;

	// inkrementuje data v zalohovacim registru
	RTC->BKP0R++;

	// zakaze zapis do zalovacich registru
	PWR->CR &= ~PWR_CR_DBP;
}

void zapniPohotovostniRezim(void)
{
	// povoli probuzeni pomoci budici linky 1 (PA0)
	PWR->CSR |= PWR_CSR_EWUP1;

	// vynuluje priznak probuzeni
	PWR->CR |= PWR_CR_CWUF;

	// vypne zdroj referencniho napeti, s nim se
	// vypne i BOR, PVD a interni senzor teploty
	PWR->CR |= PWR_CR_ULP;

	// nastavi pohotovostni rezim pri operaci "wfi"
	PWR->CR |= PWR_CR_PDDS;
	SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

	// zapne odstaveny rezim
	asm("wfi");
}

static uint8_t data = 'x';

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

	nastavUart();

	if((PWR->CSR & PWR_CSR_SBF) == PWR_CSR_SBF)
	{
		// vynuluje priznak probuzeni
		PWR->CR |= PWR_CR_CSBF;

		// odesle data
		USART2->TDR = RTC->BKP0R;

		// cekej na odeslani dat
		while((USART2->ISR & USART_ISR_TC) != USART_ISR_TC);

		inkrementujZalohovaciRegistr();
	}

	// odesle data
	USART2->TDR = data++;

	// cekej na odeslani dat
	while((USART2->ISR & USART_ISR_TC) != USART_ISR_TC);

	// cas na reset (cca 2 sekundy)
	for(uint32_t x = 0U; x < 500000; x++);

	zapniPohotovostniRezim();
}
