/**
 * Projekt Kap10-GPTIM-02
 * ======================
 *
 * Nutzt Kanal 1 des Timers TIM12 zum Ansteuern einer LED. Neben der Nutzung
 * des Compare-Modus ist hier auch die Programmierung der alternativen
 * Funktion von PIN14 von GPIOB interessant.
 */

/**
 ******************************************************************************
 * @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 <stdint.h>
#include <stdbool.h>

#include <stm32f4xx.h>
#include <mcalGPIO.h>
#include <mcalTimer.h>

/**
 * Globale Variablen
 */
bool tim12Ch2PulseDetected = false;

void TIM8_BRK_TIM12_IRQHandler(void);

int main(void)
{
    /**
     * Aktiviere GPIOB-Clock und konfiguriere PIN14 und PIN15.
     */
    gpioInitPort(GPIOB);
    gpioSelectPinMode(GPIOB, PIN14, ALTFUNC);
    gpioSelectAltFunc(GPIOB, PIN14, AF9);

    gpioSelectPinMode(GPIOB, PIN15, ALTFUNC);
    gpioSelectAltFunc(GPIOB, PIN15, AF9);

    /**
     * Aktiviere und konfiguriere TIM12/Kanal 1 als Output
     */
    timerBusClkOn(TIM12);
    timerSetPrescaler(TIM12, (1600 - 1));
    timerSetAutoReloadValue(TIM12, (5000 - 1));

    // Der Output (Channel 1, CH1) soll bei jedem Impuls invertiert werden ("toggle")
    if (timerSetCapCompMode(TIM12, TIMIO_CH1, TIMIO_OUTPUT, CHN_TOGGLE) == true)
    {
        timerSetPreloadValue(TIM12, TIMIO_CH1, 0);
        timerResetCounter(TIM12);
    }

    /**
     * Konfiguration TIM12, Channel 2 (CH2).
     */
    // CC2S_Msk konfiguriert Kanal 2 automatisch als Output.
    TIM12->CCMR1 &= ~(TIM_CCMR1_CC2S_Msk  |  // Reset TIM12 CC2S
                      TIM_CCMR1_OC2CE_Msk |  // Reset TIM12 OC2CE
                      TIM_CCMR1_OC2M_Msk);   // Reset TIM12 OC2M

    TIM12->CCMR1 |= TIM_CCMR1_CC2S_1;        // TIM12: Kanal 2 = Input, verbunden mit CH1
    TIM12->CCER  |= TIM_CCER_CC2E;           // TIM12: Aktiviere Capture/Compare fuer CH2
    TIM12->DIER  |= TIM_DIER_CC2IE;          // TIM12: Aktiviere CH2 Interrupt

    TIM12->CNT  = 0;                         // Reset Counter
    timerStart(TIM12);                       // Starte Timer

    NVIC_EnableIRQ(TIM8_BRK_TIM12_IRQn);     // NVIC: "Anmelden" des TIM12-Interrupts

    while(1)
    {
        // Wenn CH2 10 Impulse erkannt hat, wird der Timer angehalten.
        if (tim12Ch2PulseDetected)
        {
            timerStop(TIM12);
            tim12Ch2PulseDetected = false;
        }
    }
}

/**
 * @brief ISR fuer TIM12
 */
void TIM8_BRK_TIM12_IRQHandler(void)
{
    static uint8_t count = 0;

    if (TIM12->SR & TIM_SR_CC2IF)
    {
        TIM12->SR &= ~TIM_SR_CC2IF;

        ++count;

        // Nach 10x Toggeln wird der Timer gestoppt.
        if (count > 9)
        {
            tim12Ch2PulseDetected = true;
        }
    }
}
