#include "stm32f401xe.h" /* include pin, register, bit, periphery definitions */

#define USE_TIMER (0)

/* function main can have 'void' return type as it is
 * meant to never end */
int main(void)
{
  /* Init goes here */
  /* Every periphery has its typedef that groups its registers *
   * each periphery is memory mapped to some location and accessible
   * via pointer */
  /* Start GPIOA clock, we wish to modify just this one bit,
   * resetting other bits to 0 would deactivate any periphery that we've
   * enabled prior to this or that is enabled by default (look in the 6. RCC
   * section of the reference manual) */
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
  /* LED LD1 is connected to pin PA5 */
  GPIOA->MODER |= GPIO_MODER_MODE5_0; /* Configure PA5 as output, default is input mode
                                         (third state, see GPIO pin schematic in RM) */

#if USE_TIMER == 1
  /* Study section 13 regarding TIM2 in RM */
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; /* Enable clock for TIM2 */

  TIM2->CR1 = TIM_CR1_URS; /* Under/overflow generates update event */
  TIM2->CNT = 0; /* Init counter value */
  TIM2->PSC = 0; /* TODO: set prescaler to match desired frequency */
  TIM2->ARR = 0; /* TODO: set auto-reload (period) value to match desired frequency */
  TIM2->CCMR1 = 0;  /* Disable capture&compare */
  TIM2->DIER = TIM_DIER_UIE; /* Enable Update interrupt flag generation */
  TIM2->CR1 |= TIM_CR1_CEN; /* Enable counter */
#endif
  /* Main program loop */
  while(1)
  {
    /* Magic goes here*/
#if USE_TIMER == 0
    GPIOA->ODR |= GPIO_ODR_OD5; /* Set PA5 to 1 */
    /* Wait, approx. 75 ms, f_clk/cycle_duration (16 MHz/(4 * 300000), 4 ASM instruction clocks) */
    for(int i = 0; i < 300000; ++i) {}
    GPIOA->ODR &= ~GPIO_ODR_OD5; /* Set PA5 to 0, turn off the LED */
    /* Wait, approx. 75 ms, f_clk/cycle_duration (16 MHz/(4 * 300000), 4 ASM instruction clocks) */
    for(int i = 0; i < 300000; ++i) {}
#else
    if(TIM2->SR & TIM_SR_UIF)
    {
      /* Clear Update flag, toggle LED */
      TIM2->SR &= ~(TIM_SR_UIF);
      GPIOA->ODR ^= GPIO_ODR_OD5;
    }
#endif
  }

  /* Program should never leave main program loop         *
   * since anything beyond is uncharted and unpredictible */
  return 0;
}
