/**
 * Kap11-GPTIM-01
 * ==============
 *
 * Nutzt Kanal 1 des Timers TIM12 als Taktgeber zum Ansteuern einer LED. Neben
 * der Nutzung der Betriebsart "Output Compare" ist dieses Beispiel auch eine
 * Demonstration zur Anwendung der alternativen Funktionen der GPIOs.
 */

#include <stdint.h>
#include <stdbool.h>

/**
 * Kommentar in Zeile 16 entfernen, wenn Sie die MCAL testen möchten.
 */
//#define MCAL

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

int main(void)
{
    GPIO_TypeDef *port = GPIOB;
    TIM_TypeDef  *tim  = TIM12;

#ifdef MCAL     // Beginn der MCAL-Version


    // PB14 ist der Output-Compare-Ausgang von TIM12
    gpioSelectPort(port);
    gpioSelectPinMode(port, PIN14, ALTFUNC);
    gpioSelectAltFunc(port, PIN14, AF9);

    // Basis-Konfiguration von TIM12
    timerSelectTimer(tim);
    timerSetPrescaler(tim, 1600);
    timerSetAutoReloadValue(tim, 5000);

    // Output-Compare-Konfiguration von TIM12
    timerSetOutputCompareMode(tim, TIMIO_CH1, CHN_TOGGLE_ON_MATCH);
    timerEnableOutputComparePreload(tim, TIMIO_CH1);
    timerEnableCaptureCompareChannel(tim, TIMIO_CH1);
    timerResetCounter(tim);
    timerStartTimer(tim);

#else           // Ende der MCAL-Version, Beginn: Direkte Registerprogrammierung

    // GPIOB: Bustakt anschalten
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;     // GPIOB: Bustakt aktivieren

    // GPIOB / Pin 14: Alternative Funktion aktivieren
    port->MODER  &= ~GPIO_MODER_MODER14_Msk; // PB14: Reset auf Input
    port->MODER  |= GPIO_MODER_MODER14_1;    // PB14: AF-Modus aktivieren

    // AF9 auswaehlen: 27 ... 24 = 0b1001
    port->AFR[1] &= ~GPIO_AFRH_AFSEL14_Msk;  // PB14: AF zuruecksetzen
    port->AFR[1] |= GPIO_AFRH_AFSEL14_3 | GPIO_AFRH_AFSEL14_0;

    // TIM12: Basis-Konfiguration
    RCC->APB1ENR |= RCC_APB1ENR_TIM12EN;    // TIM12: Bustakt einschalten
    tim->PSC     = (1600 - 1);              // TIM12: Prescaler einstellen
    tim->ARR     = (5000 - 1);              // TIM12: Auto-Reload-Wert setzen

    // TIM12: CCMR1 in Zustand nach Reset setzen + anschliessend
    // gewuenschte Betriebsart (hier: Toggle on Match) auswaehlen.
    // Dann Output-Compare: Preload aktivieren
    TIM12->CCMR1 &= ~(TIM_CCMR1_CC1S_Msk | TIM_CCMR1_OC1M_Msk);
    TIM12->CCMR1 |= TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1;
    TIM12->CCMR1 |= TIM_CCMR1_OC1PE;

    TIM12->CCR1 = 0;
    TIM12->CCER |= TIM_CCER_CC1E;
    TIM12->CNT  = 0;
    TIM12->CR1  |= TIM_CR1_CEN;             // TIM12: Starten

#endif          // Ende: Direkte Registerprogrammierung

    while (1)
    {
    }
}
