/* ***************************************************************************************
 *  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        500
#define FIRST_LED 0
#define LAST_LED 3


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


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


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

    GPIO_init();

    __enable_irq();         // enable interrupts globally


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


    /* --- infinite processing loop --- */
    while (1)
    {
        /* ... add your code to implement the lab assignment ... */
        int direction;
        int i = 0;
        while(1){
            if(i == FIRST_LED){
                direction = 1;
            }
            else if(i == LAST_LED){
                direction = -1;
            }
            blink(i);
            if(direction > 0){
                i++;
            }
            else if(direction < 0){
                i--;
            }
        }



        switch (state) {
            case 0:
                GPIOA->ODR &= ~(1 << 0); // LED0 on
                GPIOA->ODR &= ~(1 << 1);
                GPIOA->ODR &= ~(1 << 2);
                GPIOA->ODR &= ~(1 << 3);

                state++;
                break;
            case 1:
                delay(WAITTIME);            // wait
                state++;
                break;
            case 2:
                GPIOA->ODR |= (1 << 0);     // LED0 off
                GPIOA->ODR |= (1 << 1);
                GPIOA->ODR |= (1 << 2);
                GPIOA->ODR |= (1 << 3);
                delay(WAITTIME);            // wait
                state = 0;
                break;
            default:
                break;
        }
    }

    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


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


/* ------------------------------------------------------------------------------------ *\
 * 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)
    {
        for (uint16_t j = 0; j < LOOPS_PER_MS; ++j)
        {
            __asm("NOP");
        }
    }
}

static void blink(const uint numLED)
{
    switch (state) {
                case 0:
                    GPIOA->ODR &= ~(1 << numLED); // LED0 on
                    state++;
                    break;
                case 1:
                    delay(WAITTIME);            // wait
                    state++;
                    break;
                case 2:
                    GPIOA->ODR |= (1 << numLED);     // LED0 off
                    delay(WAITTIME);            // wait
                    state = 0;
                    break;
                default:
                    break;
}


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