#include "FreeRTOS.h"
#include "os_task.h"

/* Include HET header file - types, definitions and function declarations for system driver */
#include "het.h"
#include "esm.h"
/* USER CODE END */

/* Include Files */

#include "sys_common.h"
#include "system.h"
#include "sci.h"
#include <stdio.h>
#include "os_queue.h"
#include "os_semphr.h"

/* USER CODE BEGIN (1) */
extern void EMAC_LwIP_Main (uint8_t * emacAddress);
extern void echo_init(void);
extern void gioInit(void);

//unsigned int g_BoardIpAddr;

// Define Task Handles
xTaskHandle xTask1Handle;
xTaskHandle xTask2Handle;
xTaskHandle xTask3Handle;
xTaskHandle xTask4Handle;



//xQueueHandle myQueue;


//xTaskHandle xinttaskHandle;

uint8_t     emacAddress[6]  =   {0x00, 0x08, 0xEE, 0x03, 0xA6, 0x6C};
uint32_t    emacPhyAddress  =   1;

/*//To check Mutex
xSemaphoreHandle xMutex;

xTaskHandle xTask5Handle = NULL;
xTaskHandle xTask6Handle = NULL;*/

/* USER CODE END


* @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.*/


// USER CODE BEGIN (2)
//Task1
void vTask1(void *pvParameters)
{
    EMAC_LwIP_Main (emacAddress);
  while(1)
   {
     echo_init();
       // TCPConnectionConfig(g_BoardIpAddr);
   }

}


//Task2
void vTask2(void *pvParameters)
{


   // To check Queue Functioning
    /*char myTxBuffer[30];
    myQueue = xQueueCreate(5, sizeof(myTxBuffer));
    sprintf(myTxBuffer, "message 1");
    xQueueSend(myQueue, (void *)myTxBuffer,( portTickType ) 0 );
*/

    portTickType myLastUnblock;
    myLastUnblock= xTaskGetTickCount();

    for(;;)
    {

         //Taggle HET[1] with timer tick
        gioSetBit(hetPORT1, 17, gioGetBit(hetPORT1, 17) ^ 1);
        vTaskDelayUntil( &myLastUnblock , 1000 * configTICK_RATE_HZ / 1000 );
    }
}

// Task3
 void vTask3(void *p)
{

    sciInit();
    sciSend(scilinREG, 2, (unsigned char *) "\r\n");
    sciSend(scilinREG, 7, pcTaskGetTaskName(xTask2Handle));


    int count = (int*) p;
    for(;;)
    {

        gioSetBit(hetPORT1, 27, gioGetBit(hetPORT1, 27) ^ 1);
        count++;
        vTaskDelay(1000);
       // puts("Hello");
        xTaskHandle tskHand;
        tskHand= xTaskGetCurrentTaskHandle();


        if(count == 20){
        vTaskDelete(tskHand);
        }
    }
}

//Task 4
void vTask4(void *p)
{
    for(;;)
        {
            vTaskDelay(5000 * configTICK_RATE_HZ / 1000);
            vTaskSuspend(xTask2Handle);
            vTaskDelay(5000 * configTICK_RATE_HZ / 1000);
            vTaskResume(xTask2Handle);
        }
}

// Handling Semaphore

/*void vTask5(void *p)
{
    while(1)
    {
        if(xSemaphoreTake(xMutex,( portTickType ) 10 ) == pdTRUE)
        {
            gioSetBit(hetPORT1, 17, gioGetBit(hetPORT1, 17) ^ 1);

            xSemaphoreGive(xMutex);
        }

        vTaskDelay(1000);

    }
}

void vTask6(void *p)
{
    while(1)
    {
        if(xSemaphoreTake(xMutex,( portTickType ) 10 ) == pdTRUE)
        {
                  gioSetBit(hetPORT1, 27, gioGetBit(hetPORT1, 27) ^ 1);

                  xSemaphoreGive(xMutex);
         }

        vTaskDelay(100);
    }
}*/
// Interrupt Handling
/*
void intTask(void *p)
{
    for(;;)
    {
        vTaskSuspend(NULL);
        gioSetBit(hetPORT1, 27, gioGetBit(hetPORT1, 27) ^ 1);


    }
}
void EXTI15_10_IRQHandler(void)
{



        // Resume the suspended task.
        portBASE_TYPE xYieldRequired;
        xYieldRequired = xTaskResumeFromISR( xinttaskHandle );

        if( xYieldRequired == pdTRUE )
         {
                 // We should switch context so the ISR returns to a different task.
                 // NOTE:  How this is done depends on the port you are using.  Check
                 // the documentation and examples for your port.
           portYIELD_FROM_ISR();
          }
}
*/

// Task 4
/*void vTask4(void *p){

    char myRxBuff[30];

    while(1){
        if( myQueue != 0 )
            {
                if( xQueueReceive( myQueue, ( void * ) myRxBuff, ( portTickType ) 5 ))
                {
                    printf("data received : %s\r\n",myRxBuff );
                  //  sciSend(scilinREG, 2, (unsigned char *) "\r\n");
                   // sciSend(scilinREG, 10, myRxBuff);

                }
            }
    }
}*/

/* USER CODE END */



volatile unsigned int i;

void main(void)
{

/* USER CODE BEGIN (3) */

    //Interrupt Handling
  /*_enable_IRQ();
    gioInit();
    gioEnableNotification(7);
    //To make GIOA7 as push button
     while(1)
    {
    if( gioGetBit(gioPORTA,7))
    {
      hetREG1->DOUT =  0x00000000;
    }
    else
    {
      hetREG1->DOUT =   0xFFFFFFFF;
    }
    } */

    //printf("Hello");
   // fflush (stdout);


    //Set high end timer GIO port hetPort pin direction to all output
   // printf("Hello World!\n");
    gioSetDirection(hetPORT1, 0xFFFFFFFF);
    int pass =10;


  //   Create Task 1
    if (xTaskCreate(vTask1, (const signed char *)"Task1", configMINIMAL_STACK_SIZE, NULL, 1, &xTask1Handle) != pdTRUE)
    {
         //Task could not be created
       while(1);
    }

   //  Create Task 2
    if (xTaskCreate(vTask2, (const signed char *)"Task2", configMINIMAL_STACK_SIZE, NULL, 2, &xTask2Handle) != pdTRUE)
    {
        // Task could not be created
        while(1);
    }

   //  Create Task 3
    if (xTaskCreate(vTask3, (const signed char *)"Task3", configMINIMAL_STACK_SIZE, (void *) pass, 2, &xTask3Handle) != pdTRUE)
    {
         //Task could not be created
        while(1);
    }
    //  Create Task 4
    if (xTaskCreate(vTask4, (const signed char *)"Task4", configMINIMAL_STACK_SIZE, NULL, 2, &xTask4Handle) != pdTRUE)
        {
             //Task could not be created
            while(1);
        }

    //To check Mutex
/*

    xMutex = xSemaphoreCreateMutex();

    if (xTaskCreate(vTask5, (const signed char *)"Task5", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTask5Handle) != pdTRUE)
            {
                // Task could not be created
                while(1);
            }
    if (xTaskCreate(vTask6, (const signed char *)"Task5", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTask6Handle) != pdTRUE)
              {
                  // Task could not be created
                  while(1);
              }
*/


/*    if (xTaskCreate(intTask, (const signed char *)"Task5", configMINIMAL_STACK_SIZE, NULL, 2, &xinttaskHandle) != pdTRUE)
         {
              Task could not be created
             while(1);
         }*/
    /* Start Scheduler */
    vTaskStartScheduler();

    /* Run forever */
    while(1);
/* USER CODE END */
}


/* USER CODE BEGIN (4) */
/* USER CODE END */
