#include <stdbool.h>

#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>

#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>

// #include <ti/drivers/EMAC.h>
#include <ti/drivers/GPIO.h>
// #include <ti/drivers/I2C.h>
// #include <ti/drivers/SDSPI.h>
// #include <ti/drivers/SPI.h>
#include <ti/drivers/UART.h>
// #include <ti/drivers/USBMSCHFatFs.h>
// #include <ti/drivers/Watchdog.h>
// #include <ti/drivers/WiFi.h>

#include "Board.h"
#include "displayData.h"
#include "44_ielad_lib_EXT/ieladLib.h"

#define TASKSTACKSIZE   4096

Task_Struct task0Struct;
Char task0Stack[TASKSTACKSIZE];

Task_Struct task1Struct;
Char task1Stack[TASKSTACKSIZE];

Task_Struct task2Struct;
Char task2Stack[TASKSTACKSIZE];

Void heartBeatFxn(UArg arg0, UArg arg1)
{
    while (1)
    {
        Task_sleep((unsigned int)arg0);
        GPIO_toggle(Board_LED0);
    }
}

int initDisplayUART(void)
{
    if(displayUARTHandle == NULL)
    {
        UART_Params uartParams;
        UART_Params_init(&uartParams);
        uartParams.readMode       = UART_MODE_BLOCKING;
        uartParams.writeMode      = UART_MODE_BLOCKING;
        uartParams.readDataMode   = UART_DATA_BINARY;
        uartParams.writeDataMode  = UART_DATA_BINARY;
        uartParams.baudRate       = 115200;
        uartParams.readReturnMode = UART_RETURN_FULL;
        uartParams.readEcho       = UART_ECHO_OFF;
        uartParams.dataLength     = UART_LEN_8;
        uartParams.stopBits       = UART_STOP_ONE;
        uartParams.parityType     = UART_PAR_NONE;
        displayUARTHandle = UART_open(EK_TM4C1294XL_UART1, &uartParams);

        if(displayUARTHandle == NULL)
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    return 1;
}

int openDataUART(void)
{
    if(dataUARTHandle == NULL)
    {
        UART_Params uartParams;
        UART_Params_init(&uartParams);

        uartParams.readMode       = UART_MODE_BLOCKING;
        uartParams.writeMode      = UART_MODE_BLOCKING;
        uartParams.readDataMode   = UART_DATA_BINARY;
        uartParams.writeDataMode  = UART_DATA_BINARY;
        uartParams.baudRate       = 115200;
        uartParams.readReturnMode = UART_RETURN_FULL;
        uartParams.readEcho       = UART_ECHO_OFF;
        uartParams.dataLength     = UART_LEN_8;
        uartParams.stopBits       = UART_STOP_ONE;
        uartParams.parityType     = UART_PAR_NONE;
        uartParams.readTimeout    = 1000;

        dataUARTHandle = UART_open(EK_TM4C1294XL_UART2, &uartParams);

        if(dataUARTHandle == NULL)
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    return 1;
}

void initClock(void)
{
    Clock_Params clockParams;

    Clock_Params_init(&clockParams);
    clockParams.period = 1000;
    clockParams.startFlag = true;
    Clock_create((ti_sysbios_knl_Clock_FuncPtr)clockFxn, clockParams.period, &clockParams, NULL);
}

void initMailbox(void)
{
    Mailbox_Params mailboxParams;

    Mailbox_Params_init(&mailboxParams);
    dataTxMailbox = Mailbox_create(sizeof(ieladMsg), 10, &mailboxParams, NULL);
}

int main(void)
{
    Task_Params taskParams;
    /* Call board init functions */
    Board_initGeneral();
    // Board_initEMAC();
    Board_initGPIO();
    // Board_initI2C();
    // Board_initSDSPI();
    // Board_initSPI();
     Board_initUART();
    // Board_initUSB(Board_USBDEVICE);
    // Board_initUSBMSCHFatFs();
    // Board_initWatchdog();
    // Board_initWiFi();

    initDisplayUART();
    openDataUART();

    initClock();
    initMailbox();

    /* Construct heartBeat Task  thread */
    Task_Params_init(&taskParams);
    taskParams.arg0 = 1000;
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack = &task0Stack;
    Task_construct(&task0Struct, (Task_FuncPtr)heartBeatFxn, &taskParams, NULL);

    /* Construct Task 0 thread */
    Task_Params_init(&taskParams);
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack = &task1Stack;
    Task_construct(&task1Struct, (Task_FuncPtr)dataTxTaskFxn, &taskParams, NULL);

    /* Construct Task 1 thread */
    Task_Params_init(&taskParams);
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack = &task2Stack;
    Task_construct(&task2Struct, (Task_FuncPtr)displayDataRxTaskFxn, &taskParams, NULL);

     /* Turn on user LED */
    GPIO_write(Board_LED0, Board_LED_ON);

    System_printf("Starting the example\nSystem provider is set to SysMin. "
                  "Halt the target to view any SysMin contents in ROV.\n");
    /* SysMin will only print to the console when you call flush or exit */
    System_flush();

    /* Start BIOS */
    BIOS_start();

    return (0);
}
