/* ***************************************************************************************
 *  Project:    task1 - C:GPIO
 *  File:       task1.c
 *
 *  Language:   C
 *
 *  Hardware:   STefi Light v1.1
 *  Processor:  STM32G431KBT6U
 *
 *  Author:     Manuel Lederhofer
 *  Datum:      10.09.2021
 *
 *  Version:    2.1
 *  History:
 *      10.09.2021  ML  create project
 *      09.03.2022  ML  port from STM32F042K6T6 to STM32G431KBT6U
 *      18.02.2025  TK  changed projectname to "C: GPIO)
 *
 *  Status:     under development
 *
 *  Description:
 *          Blinks the red LED of STefi Light, currently.
 *          This file contains the main routine and the initialization.
 *
 *  Notes:
 *      - MCU speed at startup is 16 MHz
 *
 *  Todo:
 *      - Change the example code to match the description and requirements
 *          of the requested application in the lab exercise guide.
 *
 ************************************************************************************** */

/* ------------------------------------ INCLUDES -------------------------------------- */
#include "stm32g431xx.h"
#include "STefi-Light.h"

/* ------------------------------------ DEFINES --------------------------------------- */
#define LOOPS_PER_MS    1244             // NOP-loops for delay()
#define WAITTIME        333

/* ------------------------------------ TYPE DEFINITIONS ------------------------------ */
/* ------------------------------------ GLOBAL VARIABLES ------------------------------ */
int state = 0;

/* ------------------------------------ PRIVATE VARIABLES ----------------------------- */

/* ------------------------------------ PROTOTYPES ------------------------------------ */
static void GPIO_init(void);
static void delay(const uint16_t ms);

/* ------------------------------------ M A I N --------------------------------------- */
int main(void)
{
    /* --- initialization --- */
    __disable_irq();        // disable interrupts globally

    GPIO_init();

    __enable_irq();         // enable interrupts globally

    /* --- one time tasks --- */

    //s0 Hilfvariablen auserhalb von while deklarieren
    int running = 0;  //0 Lauflicht aus, 1 Lauflicht an
    int lastButtonState = 1; // Hilfsvariable zur Flankenerkennung

    /* --- infinite processing loop --- */
    while (1)
    {
        int buttonState = GPIOB->IDR & (1 << 0);

        // fallende Flanke erkennen
        if (lastButtonState && !buttonState)
        {
            running ^= 1;   // toggle running
           /* delay(50);     // entprellen */
        }

        lastButtonState = buttonState;


        if(running)
        {
            switch (state)
            {
            case 0:
                state++;
                GPIOA->ODR &= ~(1 << 0);
                delay(WAITTIME);
                GPIOA->ODR |= (1 << 0);
                break;
            case 1:
                state++;
                GPIOA->ODR &= ~(1 << 1);
                delay(WAITTIME);
                GPIOA->ODR |= (1 << 1);
                break;
            case 2:
                state++;
                GPIOA->ODR &= ~(1 << 2);
                delay(WAITTIME);
                GPIOA->ODR |= (1 << 2);
                break;
            case 3:
                state++;
                GPIOA->ODR &= ~(1 << 3);
                delay(WAITTIME);
                GPIOA->ODR |= (1 << 3);
                break;
            case 4:
                state++;
                GPIOA->ODR &= ~(1 << 2);
                delay(WAITTIME);
                GPIOA->ODR |= (1 << 2);
                break;
            case 5:
                state=0;
                GPIOA->ODR &= ~(1 << 1);
                delay(WAITTIME);
                GPIOA->ODR |= (1 << 1);
                break;

            case 99:
                GPIOA->ODR |= MASK_LED_ALL;
                while(1){
                    if((GPIOB->IDR & (1 << 0)) == 0){
                        delay(150);
                        state=0;
                        break;
                    }
                }
            }
        }

    }
    //aktuell geht er mit drücken durch die cases
    // wegen break geht er ganz aus der if bedingung raus, nicht nur ausm switch case


return 1;
}

/* ------------------------------------ GLOBAL FUNCTIONS ------------------------------ */

/* ------------------------------------ PRIVATE FUNCTIONS ----------------------------- */

/* ------------------------------------------------------------------------------------ *\
 * method:  static void GPIO_init(void)
 *
 * Initializes GPIOs on STefi Light for pins with peripherals attached.
 *
 * requires:    - nothing -
 * parameters:  - none -
 * returns:     - nothing -
 \* ------------------------------------------------------------------------------------ */
static void GPIO_init(void)
{
/* enable port clocks */
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;    // LEDs: A
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;  //Taster versuch

/* --- LEDs --- */
GPIOA->ODR |= MASK_LED_ALL;
GPIOA->MODER &= ~(3 << 0);
GPIOA->MODER |= (1 << 0);               // set LED pin to output

/* LED1 als Output */
GPIOA->MODER &= ~(3 << 2);     // Versuch: LED 1 Mode löschen :klappt so
GPIOA->MODER |= (1 << 2);      // Versuch: LED 1 PA1 = output :klappt so

/* LED2 als Output */
GPIOA->MODER &= ~(3 << 4);     // Versuch: LED 2 Mode löschen :klappt
GPIOA->MODER |= (1 << 4);      // Versuch: LED 2 PA1 = output :klappt

/* LED3 als output */
GPIOA->MODER &= ~(3 << 6);
GPIOA->MODER |= (1 << 6);

/* s0 (PB0) als Input Versuch */
GPIOB->MODER &= ~(3 << 0);

/* Pull-Up Aktivieren Versuch */
GPIOB->PUPDR &= ~(3 << 0);
GPIOB->PUPDR |= (1 << 0);  // 01 = Pull-Up
}

/* ------------------------------------------------------------------------------------ *\
 * method:  static void delay(const uint16_t ms)
 *
 * Realizes a millisecond delay by very bad busy-wait.
 *
 * requires:    - nothing -
 * parameters:  ms - delay time in milliseconds
 * returns:     - nothing -
 \* ------------------------------------------------------------------------------------ */
static void delay(const uint16_t ms)
{
for (uint16_t i = 0; i < ms; ++i)
{
    if((GPIOB->IDR & (1 << 0) && state != 99) == 0){
        state = 99;
        break;
    }
    for (uint16_t j = 0; j < LOOPS_PER_MS; ++j)
    {
        __asm("NOP");
    }
}
}

/* ************************************ E O F ***************************************** */
