#include <stdio.h> // sprintf() for debugging
#include "hal.h"
#include "riscv_hal.h"
#include "hw_platform.h"
#include "drivers/CoreGPIO/core_gpio.h"

// Delay values for delay() function
#define delay_1ms	 730				// about 1ms delay @50MHz MiV Clock, Small MiV Core
#define delay_10ms	 10*delay_1ms
#define delay_100ms  100*delay_1ms
#define delay_500ms  500*delay_1ms
#define delay_1000ms 1000*delay_1ms


/******************************************************************************
 * Local functions.
 *****************************************************************************/

void Init(void);
void delay1(volatile uint32_t n);

/******************************************************************************
 * GPIO instance data.
 *****************************************************************************/
gpio_instance_t g_gpio0;


/******************************************************************************
 * main function.
 *****************************************************************************/ 
int main( void )
{
    uint8_t stop_test = 0;

	Init();

    while (!stop_test) {

    	// Toggle LED0, ~1Hz
        GPIO_set_output(&g_gpio0, GPIO_0, 1);
        delay1(delay_500ms);
        GPIO_set_output(&g_gpio0, GPIO_1, 1);
        GPIO_set_output(&g_gpio0, GPIO_0, 0);
        delay1(delay_500ms);
        GPIO_set_output(&g_gpio0, GPIO_2, 1);
        GPIO_set_output(&g_gpio0, GPIO_1, 0);
        delay1(delay_500ms);
        GPIO_set_output(&g_gpio0, GPIO_3, 1);
        GPIO_set_output(&g_gpio0, GPIO_2, 0);
        delay1(delay_500ms);
        GPIO_set_output(&g_gpio0, GPIO_4, 1);
        GPIO_set_output(&g_gpio0, GPIO_3, 0);
        delay1(delay_500ms);
        GPIO_set_output(&g_gpio0, GPIO_5, 1);
        GPIO_set_output(&g_gpio0, GPIO_4, 0);
        delay1(delay_500ms);
        GPIO_set_output(&g_gpio0, GPIO_6, 1);
        GPIO_set_output(&g_gpio0, GPIO_5, 0);
        delay1(delay_500ms);
        GPIO_set_output(&g_gpio0, GPIO_7, 1);
        GPIO_set_output(&g_gpio0, GPIO_6, 0);
        delay1(delay_500ms);
        GPIO_set_output(&g_gpio0, GPIO_0, 1);
        GPIO_set_output(&g_gpio0, GPIO_7, 0);
        delay1(delay_500ms);


    }


}

// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
// Setup functions

void Init(void)
{

	// Initialize RISC-V platform level interrupt controller
	PLIC_init();

    // Disable interrupts in general.
    HAL_disable_interrupts();

	// Initialize the CoreGPIO driver with the base address of the CoreGPIO
	// instance to use and the initial state of the outputs.
    GPIO_init(&g_gpio0, COREGPIO_BASE_ADDR, GPIO_APB_32_BITS_BUS);

	// Configure the GPIOs.
    GPIO_config( &g_gpio0, GPIO_0, GPIO_OUTPUT_MODE );
    GPIO_config( &g_gpio0, GPIO_1, GPIO_OUTPUT_MODE );
    GPIO_config( &g_gpio0, GPIO_2, GPIO_OUTPUT_MODE );
    GPIO_config( &g_gpio0, GPIO_3, GPIO_OUTPUT_MODE );
    GPIO_config( &g_gpio0, GPIO_4, GPIO_OUTPUT_MODE );
    GPIO_config( &g_gpio0, GPIO_5, GPIO_OUTPUT_MODE );
    GPIO_config( &g_gpio0, GPIO_6, GPIO_OUTPUT_MODE );
    GPIO_config( &g_gpio0, GPIO_7, GPIO_OUTPUT_MODE );

    GPIO_set_output(&g_gpio0, GPIO_0, 0);
    GPIO_set_output(&g_gpio0, GPIO_1, 0);
    GPIO_set_output(&g_gpio0, GPIO_2, 0);
    GPIO_set_output(&g_gpio0, GPIO_3, 0);
    GPIO_set_output(&g_gpio0, GPIO_4, 0);
    GPIO_set_output(&g_gpio0, GPIO_5, 0);
    GPIO_set_output(&g_gpio0, GPIO_6, 0);
    GPIO_set_output(&g_gpio0, GPIO_7, 0);

}

// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
// Simple delay function

void delay1(volatile uint32_t n) {
    while (n)
        n--;
}

// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
