/*
 * Copyright (c) 2016, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

/***
 * \file  : Dm8127_Main.c
 *
 * \brief : Source file for the DM8127_CSK_Diag.
 *
 * \b \Descr : This is the main source file for the diagnostic test
 *         it is nothing but a handler file which will handle all
 *         the diagnostic's functions used in the DM8127_CSK project.
 */

/*
 *=====================
 * Includes
 *=====================
 */
 #include "dm8127_Platform.h"
 #include "version.h"
 #include <time.h>
#include <stdlib.h>

/*
 *=====================
 * Defines
 *=====================
 */

#define SWITCH
/******  Test cases ******/
#define AUDIO_TEST       ('a')
#define BT_TEST          ('b')
#define CAMERA_TEST      ('c')
#define DDR3_TEST        ('d')
#define ETHERNET_TEST    ('e')
#define HDMI_TEST        ('h')
#define LED_TEST         ('l')
#define SD_CARD_TEST     ('m')
#define NAND_FLASH_TEST  ('n')
#define SWITCH_TEST      ('s')
#define USB_TEST         ('u')
#define COMPOSITE_VIDEO  ('v')
#define WLAN_TEST        ('w')
#define EXIT             ('x')
#define ALL_TEST         ('t')
#define LONG_RUN         ('f')

#if 0

/*
 *=====================
 * Function Definitions
 *=====================
 */

/***
 * \brief : Routine to run the test cases for DM8127_CSK interfaces.
 *
 * \b \Descr : This routine takes the function handler and param as input and
 * \n          executes the appropriate function handlers and prints the result
 * \n        as success or failure.
 *
 * \param :  funchandle  [IN]  handler function for which the test has to be
 *                             performed.
 * \n        testname    [IN]  Name of the test case.
 * \n        param       [IN]  8 bit parameter for the funchandle.
 * \n        testid      [IN]  testid, which is to keep count of number of test.
 *
 * \return  VOID
 *
 */
void TEST_execute
(
	STATUS (*funchandle )(SINT16),
	SINT8 *testname,
	SINT8 param,
	SINT16 testid
)
{
	STATUS status;
	time_t t;

	status = FAILED;
    /* Call test function */
    status = funchandle(param);

    /* Check for test fail */
    if ( status != 0 ) /* @ FAILURE */
    {
    	time(&t);
#ifdef DEBUG
    	printf ("Test Suite version number is %d.%d.\r\n", MAJOR_VERSION, MINOR_VERSION);
        printf( " %s FAIL... error code %d... : Time = %s\r\n", testname,status,ctime(&t) );
#else
        platform_write ("Test Suite version number is %d.%d.\r\n", MAJOR_VERSION, MINOR_VERSION);
        platform_write( "%s FAIL... error code %d... : Time = %s\r\n", testname,status,ctime(&t) );
#endif
    }
    else /* @ SUCCESS*/
    {
       	time(&t);
#ifdef DEBUG
        printf( " %s PASS: Time = %s\r\n", testname,ctime(&t) );
#else
        platform_write( "%s PASS: Time = %s\r\n", testname,ctime(&t) );
#endif
    }
}

 /***
  * \brief : Interface's Handler function for DM8127_CSK.
  *
  * \b \Descr : This function control the execution of Interface's diagnostic test
  * \n          This function is designed in such way that user can test
  * \n          All Interfaces .
  * \n          Or run all tests at a time. To select a particular test user has to
  * \n          Enable the switch base by defining the SWITCH Macro.
  *
  * \param : VOID
  *
  * \return: SUCCESS   on successful execution
  * \n       FAILED    if fail at any instance.
  */
SINT32 Long_run_test
(
    void
)
{
	static UINT16 TestBuff[NOI][NUMBER_OF_LOOP] = {     };
	SINT32 s32status;
	static UINT16 u16RunTest = 0;
	time_t t;
	s32status = FAILED;

	 s32status = DDR3_test(0);
	 if(s32status == SUCCESS)
	 {
		 TestBuff[2][0] = TestBuff[2][0] + 1;
		 Uart_stringSend("\r\n DDR3 patterns writing test PASS");
	 }
	 Uart_stringSend("\r\n-------------------X-------------------\r\n");

	 /*****************************************************************************/
	 s32status = FAILED;

	 s32status = NAND_Flash_Test();
	 if(s32status == SUCCESS)
	 {
		 TestBuff[6][0] = TestBuff[6][0] + 1;
		 Uart_stringSend("\r\n NAND flash test PASS");
	 }
	 Uart_stringSend("\r\n-------------------X-------------------\r\n");

	 /*****************************************************************************/
	 s32status = FAILED;

	 s32status = SD_MMC_test();
	 if(s32status == SUCCESS)
	 {
		 TestBuff[5][0] = TestBuff[5][0] + 1;
		 Uart_stringSend("\r\n SD MMC test PASS");
	 }
	 Uart_stringSend("\r\n-------------------X-------------------\r\n");

	 /*****************************************************************************/
	 s32status = FAILED;
	  s32status = emac_gmii_test();
	  if(s32status == SUCCESS)
	  {
		  TestBuff[3][0] = TestBuff[3][0] + 1;
		  Uart_stringSend("\r\n Ethernet test PASS");
	  }
	  Uart_stringSend("\r\n-------------------X-------------------\r\n");

	  /*****************************************************************************/
	  s32status = FAILED;
	  s32status = Audio_Test();
	 if(s32status == SUCCESS)
	 {
		 TestBuff[0][0] = TestBuff[0][0] + 1;
		 Uart_stringSend("\r\n Audio test PASS");
	 }
	 Uart_stringSend("\r\n-------------------X-------------------\r\n");

	 /*****************************************************************************/
	 s32status = FAILED;
	 s32status = WLAN_Test();
	 if(s32status == SUCCESS)
	 {
		 TestBuff[9][0] = TestBuff[9][0] + 1;
	 }
	 Uart_stringSend("\r\n-------------------X-------------------\r\n");

	 /*****************************************************************************/
	 s32status = FAILED;

	 s32status = BT_Test();
	 if(s32status == SUCCESS)
	 {
		 TestBuff[1][0] = TestBuff[1][0] + 1;
		 Uart_stringSend("\r\n Bluetooth chip detection test PASS");
	 }
	 Uart_stringSend("\r\n-------------------X-------------------\r\n");

	 /*****************************************************************************/
	 s32status = FAILED;

	 s32status = usb_test(PARAM_VOID);
	 if(s32status == SUCCESS)
	 {
		 TestBuff[8][0] = TestBuff[8][0] + 1;
		 Uart_stringSend("\r\n USB test PASS");
	 }
	 Uart_stringSend("\r\n-------------------X-------------------\r\n");

	 /*****************************************************************************/
	 s32status = FAILED;
	 s32status = led_test();
	 if(s32status == SUCCESS)
	 {
		 TestBuff[4][0] = TestBuff[4][0] + 1;
		 Uart_stringSend("\r\n LED blinking test PASS");
	 }
	 Uart_stringSend("\r\n-------------------X-------------------\r\n");

	 /*****************************************************************************/
	 s32status = FAILED;

	 s32status = switch_test();
	 if(s32status == SUCCESS)
	 {
		 TestBuff[7][0] = TestBuff[7][0] + 1;
		 Uart_stringSend("\r\n switch test PASS");
	 }
	 Uart_stringSend("\r\n-------------------X-------------------\r\n");

	 /*****************************************************************************/
	 s32status = FAILED;

	 s32status = camera_test(0);
	 if(s32status == SUCCESS)
	 {
		 TestBuff[10][0] = TestBuff[10][0] + 1;
		 Uart_stringSend("\r\n Camera test Completed");
	 }
	 Uart_stringSend("\r\n-------------------X-------------------\r\n");

	 /*****************************************************************************/
	 u16RunTest ++;
	/* Print the status here */
	Uart_stringSend("\n\r+=================================================+"
					"\r\n|      DM8127 CSK Hardware Diagnostic Tests       |"
					"\r\n+=================================================+"
					"\r\n    Diagnostic Tests         PASS        FAIL    "
					"\r\n    ----------------         ----        ----    ");
	 platform_write("\n       Audio Test             %d           %d  ",TestBuff[0][0],(u16RunTest - TestBuff[0][0]));
	 platform_write("\n       BT Test                %d           %d  ",TestBuff[1][0],(u16RunTest - TestBuff[1][0]));
	 platform_write("\n       DDR Test               %d           %d  ",TestBuff[2][0],(u16RunTest - TestBuff[2][0]));
	 platform_write("\n       Ethernet test          %d           %d  ",TestBuff[3][0],(u16RunTest - TestBuff[3][0]));
	 platform_write("\n       LED Test               %d           %d  ",TestBuff[4][0],(u16RunTest - TestBuff[4][0]));
	 platform_write("\n       SD/MMC Test            %d           %d  ",TestBuff[5][0],(u16RunTest - TestBuff[5][0]));
	 platform_write("\n       NAND Flash Test        %d           %d  ",TestBuff[6][0],(u16RunTest - TestBuff[6][0]));
	 platform_write("\n       Switch Test            %d           %d  ",TestBuff[7][0],(u16RunTest - TestBuff[7][0]));
	 platform_write("\n       USB Test               %d           %d  ",TestBuff[8][0],(u16RunTest - TestBuff[8][0]));
	 platform_write("\n       WLAN Test              %d           %d  ",TestBuff[9][0],(u16RunTest - TestBuff[9][0]));
	 platform_write("\n       Camera Test            %d           %d  ",TestBuff[10][0],(u16RunTest - TestBuff[10][0]));
	 Uart_stringSend("\n\r===================================================\n\r");
	 time(&t);
	 platform_write( "\nDiagnostic Tets count %d is completed at %s\n",u16RunTest, ctime(&t) );

	return(0);
}
/***
 * \brief : Interface's Handler function for DM8127_CSK.
 *
 * \b \Descr : This function control the execution of Interface's diagnostic test
 * \n          This function is designed in such way that user can perform the
 * \n          particular test by selecting the option from the given menu.
 * \n          Or run all tests at a time. To select a particular test user has to
 * \n          Enable the switch base by defining the SWITCH Macro.
 *
 * \param : VOID
 *
 * \return: SUCCESS   on successful execution
 * \n       FAILED    if fail at any instance.
 */
SINT32 diag_main
(
    void
)
{
	char u8Option;  /* User Input variable*/
	SINT32 s32status;
	UINT16 TestBuff[NOI][NUMBER_OF_LOOP] = {     };
    time_t t;
    UINT8 u8Test_cnt;
    u8Test_cnt = 0;
	s32status = FAILED;

	do
	{
		time(&t);
		platform_write( "Diagonstic test start at %s\n", ctime(&t) );
#ifdef DEBUG
		printf("\n\r+=================================================+"
		       "\r\n|         DM8127 Hardware Diagnostic Test         |"
		       "\n\r+=================================================+"
		       "\r\n|            Please choose the Option             |"
		       "\r\n|   Options                  Action               |"
			   "\r\n|-------------------------------------------------|"
			   "\r\n|     a/A                  Audio test             |"
			   "\r\n|     b/B                  Bluetooth test         |"
			   "\r\n|     c/C                  Camera Test            |"
			   "\r\n|     d/D                  DDR3 test              |"
			   "\r\n|     e/E                  Ethernet test          |"
	 		   "\r\n|     h/H                  HDMI test              |"
			   "\r\n|     l/L                  LED test               |"
			   "\r\n|     m/M                  SD/MMC card test       |"
			   "\r\n|     n/N                  NAND Flash test        |"
			   "\r\n|     s/S                  Switch test            |"
			   "\r\n|     u/U                  USB test               |"
			   "\r\n|     v/V                  Composite video        |"
			   "\r\n|     w/W                  WLAN test              |"
			   "\r\n|     x/X                  To exit from Diag test |"
			   "\r\n|     t/T                  Complete test          |"
			   "\r\n+=================================================+\r\n\n");
#else
#if 1
		Uart_stringSend("\n\r+=================================================+");
		Uart_stringSend("\r\n|        DM8127 CSK Hardware Diagnostic Test      |");
		Uart_stringSend("\n\r+=================================================+");
		Uart_stringSend("\r\n|            Please choose the Option             |");
		Uart_stringSend("\r\n|   Options                  Action               |"
						"\r\n|-------------------------------------------------|"
						"\r\n|     a/A                  Audio test             |"
						"\r\n|     b/B                  Bluetooth test         |"
						"\r\n|     c/C                  Camera Test            |"
						"\r\n|     d/D                  DDR3 test              |"
						"\r\n|     e/E                  Ethernet test          |"
						"\r\n|     h/H                  HDMI test              |"
						"\r\n|     l/L                  LED test               |"
						"\r\n|     m/M                  SD/MMC card test       |"
						"\r\n|     n/N                  NAND Flash test        |"
						"\r\n|     s/S                  Switch test            |"
						"\r\n|     u/U                  USB test               |"
						"\r\n|     v/V                  Composite video        |"
						"\r\n|     w/W                  WLAN test              |"
						"\r\n|     x/X                  To exit from Diag test |"
						"\r\n|     t/T                  Complete test          |"
						"\r\n|     f/F                  Long run test          |"
						"\r\n+=================================================+\r\n\n");
#endif
#endif

#ifdef SWITCH
	Uart_stringSend("please enter the option\r\nWaiting for user Input\r\n");
	uart_recv( Hanhler_uart0, &u8Option, uart_timeout );

	if ((u8Option >= 'A' ) && (u8Option <= 'Z') )
	{
		u8Option = u8Option + ' ';
	}
#else
	u8Option = DDR3_TEST;
#endif
	switch(u8Option)
	{
			case DDR3_TEST : /* Tested */

			s32status = DDR3_test(0);
			if(s32status == SUCCESS)
			{
				Uart_stringSend("\r\n DDR3 patterns writing test PASS");
			}
			Uart_stringSend("\r\n-------------------X-------------------\r\n");

			break;

			case NAND_FLASH_TEST : /* Tested */

			 s32status = NAND_Flash_Test();
			 if(s32status == SUCCESS)
			 {
				Uart_stringSend("\r\n NAND flash test PASS");
			 }
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");

			break;

			case SD_CARD_TEST :

			 s32status = SD_MMC_test();
			 if(s32status == SUCCESS)
			 {
				  Uart_stringSend("\r\n SD MMC test PASS");
			 }
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");

			break;

			case ETHERNET_TEST : /* Tested */

			 s32status = emac_gmii_test();
			 if(s32status == SUCCESS)
			 {
				  Uart_stringSend("\r\n Ethernet test PASS");
			 }
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");

			break;

		case AUDIO_TEST : /* Tested */

			 s32status = Audio_Test();
			 if(s32status == SUCCESS)
			 {
				  Uart_stringSend("\r\n Audio test PASS");
			 }
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");

			 break;

		case WLAN_TEST:  /* Tested */

			 s32status = WLAN_Test();
			 if(s32status == SUCCESS)
			 {
				 TestBuff[9][0] = TestBuff[9][0] + 1;
			 }
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");

			break;

		case BT_TEST : /* Tested */

			 s32status = BT_Test();
			 if(s32status == SUCCESS)
			 {
				  Uart_stringSend("\r\n Bluetooth chip detection test PASS");
			 }
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");

			break;

		case USB_TEST : /* Tested */

			 s32status = usb_test(PARAM_VOID);
			 if(s32status == SUCCESS)
			 {
				  Uart_stringSend("\r\n USB test PASS");
			 }
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");

			break;

		case LED_TEST : /* Tested */

			 s32status = led_test();
			 if(s32status == SUCCESS)
			 {
				  Uart_stringSend("\r\n LED blinking test PASS");
			 }
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");

			 break;

		case SWITCH_TEST :
			s32status = FAILED;
			 s32status = switch_test();
			 if(s32status == SUCCESS)
			 {
				  Uart_stringSend("\r\n switch test PASS");
			 }
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");

			break;

		case CAMERA_TEST : /* Tested */

			s32status = FAILED;
			 s32status = camera_test(0);
			 if(s32status == SUCCESS)
			 {
				 TestBuff[10][0] = TestBuff[10][0] + 1;
				 Uart_stringSend("\r\n Camera test Completed");
			 }
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");

			break;


		case ALL_TEST :
				Long_run_test();
			break;

		case LONG_RUN :
			Uart_stringSend("\r\nLong run test perform all tests for 100 times\r\n");
			u8Test_cnt = INIT_VAL;

			while(u8Test_cnt != 100)
			{
				Long_run_test();
				u8Test_cnt ++;
			}
				break;

		case HDMI_TEST:
			Uart_stringSend("\r\nUsage > HDMI configuration has been done when the target got connected"
					        "\r\n        if Display is connected, it shows colour BAR \r\n\n");
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");
			break;

		case COMPOSITE_VIDEO :
			Uart_stringSend("\r\nUsage > Composite video configuration has been done when the target got connected"
							"\r\n        if Display is connected, it shows colour BAR \r\n\n");
			 Uart_stringSend("\r\n-------------------X-------------------\r\n");
			break;
		case EXIT:
#ifndef DEBUG
			Uart_stringSend("Exiting from the Interface test\n\r");
#endif
#ifdef DEBUG
			printf("Exiting from the Interface test\n");
#endif
			break;

		default:
			Uart_stringSend("Invalid Input\r\n");
#ifdef DEBUG
			printf("You have entered an incorrect options\r\n");
#endif
			break;

	}
	}while(EXIT != u8Option);

	return(s32status);
}

#endif

static void displayMenu(void)
{
	UINT16 count;

	/* Print the status here */
	Uart_stringSend("\n\r==================================================================="
					"\r\n                DM8127 CSK Hardware Diagnostic Tests               "
					"\r\n==================================================================="
					"\r\n   Options      Diagnostic Tests		PASS		FAIL              "
					"\r\n   -------      ----------------		----		----      \r\n");

	for (count = 0; count < PLATFORM_TEST_COUNT; count++)
	{

		platform_write("    %2d - ",count);
		platform_write("%-30s", (const char*)gDiagTestTable[count].testName);
		platform_write("\t%3d", gDiagTestTable[count].pass);
		platform_write("\t\t%3d", gDiagTestTable[count].fail);
		platform_write("\n\r");
	}
	platform_write("\n\r");
	platform_write("    q -	 	Quit\n\r");
	Uart_stringSend("\n\r====================================================================");
	Uart_stringSend("\n\rEnter Desired Option: ");
}

static void run_all_tests(void)
{
	UINT16 index;

	platform_write("\n\n\rAuto Running All the Diagnostic Tests!\n\n\r");

	for (index = PLATFORM_TEST_START; index <= PLATFORM_AUTO_TEST_COUNT; index++)
	{
		if(gDiagTestTable[index].testFunction != NULL)
		{
			if(gDiagTestTable[index].testFunction(gDiagTestTable[index].args))
			{
				gDiagTestTable[index].fail++;
			}
			else
			{
				gDiagTestTable[index].pass++;
			}
		}
		else
		{
			platform_write("\n\nInvalid Test Handle for %s\n",
			               (const char*)gDiagTestTable[index].testName);
		}
	}

	platform_write("\nDiagnostic Tests Completed!!\n\n");
	displayMenu();
}

SINT32 diag_main (void)
{
	SINT32 status;
	UINT8         exitTest;
	UINT8         inputErr;
	UINT32        diagInput;
	char 		  testInput[2];

	exitTest = 0;
	inputErr = 0;

	/*Reading the input from the user*/

		while(!exitTest)
		{
			/* Display menu */
				displayMenu();


			testInput[0] = '\0';
			testInput[1] = '\0';

			status = platform_read(testInput, 3);
			if(status != -1)
			{
				/* Check user input */
				if((testInput[0] == 'q') || (testInput[0] == 'Q'))
				{
					exitTest = 1;
					platform_write("\n\nExiting the Diagnostic Tests!!\n\r");
					status = 0;
					break;
				}
				if((testInput[0] == 0xD) || (testInput[0] == 0x1B) || (testInput[0] == 0x1B))
				{

					continue;

				}
				else
				{
					platform_write("\n\r");
					diagInput = strtoul((const char*)testInput, NULL, 10);
					switch(diagInput)
					{
						case PLATFORM_TEST_AUTO_ALL:
							while(1)
							{
								run_all_tests();
							}
							//break;
						default:
							if(diagInput < PLATFORM_TEST_COUNT)
							{
								if(gDiagTestTable[diagInput].testFunction != NULL)
								{
									if(gDiagTestTable[diagInput].testFunction(gDiagTestTable[diagInput].args))
									{
										gDiagTestTable[diagInput].fail++;
									}
									else
									{
										gDiagTestTable[diagInput].pass++;
									}
								}
								else
								{
									platform_write("\n\nInvalid Test Handle!!\n\r");
								}
							}
							else
							{
								inputErr = 1;
							}

							if(inputErr)
							{
								inputErr = 0;
								/* Invalid input. Get the desired option again and continue */
								platform_write("\n\n\rInvalid Input!\n\r");
								platform_write("Please Enter Valid Input\n\r");
								continue;
							}

							platform_write("\n\r");
							break;

					}
				}
			}
			else
			{
				platform_write("Platform Initialization Failed!\n");
			}
		}

	return 1;

}

/***
 * \brief : Entry function for DM8127 Diagnostic test.
 *
 * \b \Descr: This function initialize the DM8127 board
 *            and call the diagnostic function for the Interfaces testing.
 *
 * \param: Void
 *
 * \return: 0
 */
int main( void )
{
	STATUS s32status;
#ifdef PENDING
	/* platform Init */
	s32status = Platform_init();
	if (SUCCESS == s32status)
	{
		Uart_stringSend("\r\nPlatform initialization done\r\n");
	}
#endif
	UART_Init();
	s32status = diag_main();
	if (SUCCESS == s32status)
	{

	}
	return(0);
}
