/**
 ******************************************************************************
 * @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 nastavGpio()
{
	// zapne hodinovy signal pro port C
	RCC->IOPENR |= RCC_IOPENR_IOPCEN;

	// vynuluje nastaveni modu pinu PC9
	GPIOC->MODER &= ~GPIO_MODER_MODE9;

	// nastavi PC9 jako vystupni pin
	GPIOC->MODER |= GPIO_MODER_MODE9_0;
}

void nastavCasovac()
{
	// zapne hodinovy signal pro TIM6
	RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;

	// nastavi delicku pro TIM2 (2097 KHz / 2097 = 1 KHz)
	TIM6->PSC = 2096U;

	// povoli preruseni pri preteceni (update)
	TIM6->DIER |= TIM_DIER_UIE;

	// povoli preruseni linky ARM jadra pro TIM2
	NVIC->ISER[0] |= (1U << TIM6_DAC_IRQn);
}

void nastavExti13()
{
	// zapne hodinovy signal pro port C
	RCC->IOPENR |= RCC_IOPENR_IOPCEN;

	// nastavi PC13 jako vstupni pin
	GPIOC->MODER &= ~GPIO_MODER_MODE13;

	// zapne hodinovy signal pro System Configuration Controller
	RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;

	// pripoji externi preruseni 13 na port C
	SYSCFG->EXTICR[3] |= SYSCFG_EXTICR4_EXTI13_PC;

	// nastavi reakci linky 13 na sestupnou hranu signalu
	EXTI->FTSR |= EXTI_FTSR_FT13;

	// povoli externi preruseni linky 13
	EXTI->IMR |= EXTI_IMR_IM13;

	// povoli externi preruseni linky 4 az 15 ARM jadra
	NVIC->ISER[0] |= (1U << EXTI4_15_IRQn);
}

void TIM6_DAC_IRQHandler()
{
	// vypne casovac
	TIM6->CR1 &= ~TIM_CR1_CEN;

	// vynuluje priznak preruseni periferie
	TIM6->SR &= ~(TIM_SR_UIF);

	// vynuluje priznak preruseni linky
	NVIC->ICPR[0] |= (1U << TIM6_DAC_IRQn);

	// vypne navrat do spiciho rezimu po opusteni ISR
	SCB->SCR &= ~(1 << SCB_SCR_SLEEPONEXIT_Pos);
}

void EXTI4_15_IRQHandler(void)
{
	// prepne vytupni uroven pinu PC9
	GPIOC->ODR ^= GPIO_ODR_OD9;

	// vynulovani priznaku preruseni
	EXTI->PR |= EXTI_PR_PIF13;

	// vynulovani priznaku preruseni v jadru ARM
	NVIC->ICPR[0] |= (1 << EXTI4_15_IRQn);
}

void zpozdeni(uint16_t pocetMilisekund)
{
	// vynuluje casovac
	TIM6->CNT = 0U;

	// nastavi AutoReload registr
	TIM6->ARR = pocetMilisekund - 1;

	// zapne casovac
	TIM6->CR1 |= TIM_CR1_CEN;

	// vrati se do spiciho rezimu po opusteni ISR
	SCB->SCR |= (1 << SCB_SCR_SLEEPONEXIT_Pos);

	// zapni spici rezim probuzeny prerusenim
	asm("wfi");
}

int main(void)
{
	nastavCasovac();

	nastavExti13();

	nastavGpio();

	while(1)
	{
		// prepne vytupni uroven pinu PC9
		GPIOC->ODR ^= GPIO_ODR_OD9;

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

		//zpozdeni(10);
	}
}
