/**
 * @brief Der STM32F4 empfaengt Daten von einem Terminal und sendet sie
 *        über die USART2-Komponente im Interruptbetrieb zurueck.
 *
 * @par
 * Einstellungen von USART2:
 * -------------------------
 * Baudrate  : 115200 bps
 * Wortlaenge: 8 Bit
 * Paritaet  : Keine
 * Stoppbits : 1
 *
 * Daten werden von einem Terminal-Emulator (unter Windows z.B. HTerm) an das
 * Nucleo-Board gesendet. Diese Daten werden anschliessend vom Nucleo-Board
 * wieder an HTerm zurueckgesendet.
 *
 * Dieses Beispiel ist eine Adaption eines Beispiels der Universitaet Ljubljana
 * und wurde geringfuegig modifiziert.
 */
/**
 ******************************************************************************
 * @file           : main.c
 * @author         : Auto-generated by STM32CubeIDE
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; Copyright (c) 2020 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 <stm32f4xx.h>
#include <stdint.h>
#include <stdbool.h>

#include <mcalGPIO.h>
#include <mcalUsart.h>

void uartTest(void);
void USART2_IRQHandler(void);

uint8_t  *outString = (uint8_t *) "The quick brown fox jumps over the lazy dog. ";

int main(void)
{
//    __disable_irq();

    // Konfiguration + Initialisierung von GPIOA
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;          // GPIOA : Bustakt aktivieren
    gpioSelectPinMode(GPIOA, PIN2, ALTFUNC);      // PA2   : Modus = Alt. Funktion
    gpioSelectAltFunc(GPIOA, PIN2, AF7);          // PA2   : AF7 = USART2 Rx
    gpioSelectPinMode(GPIOA, PIN3, ALTFUNC);      // PA3   : Modus = Alt. Funktion
    gpioSelectAltFunc(GPIOA, PIN3, AF7);          // PA3   : AF7 = USART2 Tx
    gpioSelectPinMode(GPIOA, PIN5, OUTPUT);       // PA5   : GPIO-Output fuer LED

    /**
     * Ersetzen Sie #if 1 durch #if0, wenn Sie die Funktionen
     * der mcal-Bibliothek verwenden wollen.
     */
#if 0
    // Konfiguration von USART2
    // Hier wird nur die Baudrate eingestellt. Wortlaenge, Paritaet und Anzahl
    // der Stoppbits entsprechen den Default-Einstellungne nach einem Reset.
    RCC->APB1ENR |= RCC_APB1ENR_USART2EN;         // USART2: Bustakt aktivieren
    USART2->BRR  = 0x8B;                          // USART2: Baudrate = 115200 bps
    USART2->CR1 |= USART_CR1_UE;                  // USART2: Starte USART2
    USART2->CR1 |= (USART_CR1_RE | USART_CR1_TE); // USART2: Aktiviere Receiver + Transmitter
    USART2->CR1 |= USART_CR1_RXNEIE;              // USART2: Aktiviere Receiver-Interrupt
#else
    // Hier werden sämtliche Parameter (Baudrate, Wortlaenge, Paritaet und
    // Anzahl der Stoppbits eingestellt.
    usartSelectUsart(USART2);
    usartStartUsart(USART2);
    usartSetCommParams(USART2, 115200, NO_PARITY, LEN_8BIT, ONE_BIT);
    usartEnableIrq(USART2, USART_IRQ_RXNEIE);
#endif

    NVIC_EnableIRQ(USART2_IRQn);

//    __enable_irq();

    /* Loop forever */
    while(1)
    {

    }
}

void USART2_IRQHandler(void)
{
    uint16_t received = 0;

    if (USART2->SR & USART_SR_RXNE)
    {
        received = USART2->DR & 0x01FF;
        if (received == 'a')
        {
            gpioSetPin(GPIOA, PIN5);
        }
        if (received == 'b')
        {
            gpioResetPin(GPIOA, PIN5);
        }
        if (((received >= 'A') && (received <= 'Z')) || (received == ' '))
        {
            USART2->DR = received;
        }
        if (received == 'c')
        {
            USART2->CR1 |= USART_CR1_TXEIE;
            USART2->DR   = *outString++;          // Liest alle Zeichen des vordefinierten Strings
        }
    }

    if (USART2->SR & USART_SR_TXE)
    {
        if (*outString != '\0')
        {
            USART2->DR = *outString++;
        }
        else
        {
            USART2->CR1 &= ~USART_CR1_TXEIE;
        }
    }
}
