/******************** (C) COPYRIGHT 2006 STMicroelectronics ********************
* File Name          : boardselftest.c
* Author             : MCD Application Team
* Date First Issued  : 03/10/2006
* Description        : This file includes the STR75x-EVAL board test driver.
********************************************************************************
* History:
* 07/17/2006 : V1.0
* 03/10/2006 : V0.1
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define NumberOfTests     10          /* Number of tests */
#define M25P64_ID         0x202017    /* M25P64 SPI Flash ID */
#define TestBoardSector   0x620000    /* SMI Flash test sector */

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

  /* Peripherals InitStructure define */
  extern GPIO_InitTypeDef  GPIO_InitStructure;
  extern ADC_InitTypeDef   ADC_InitStructure;
  UART_InitTypeDef         UART_InitStructure;

  extern vu8 SelectedWave;       /* Osiris or recorded wave playing select */
  extern vu8  VoiceRecord;       /* Boardself test record or voice recordering select */
  extern vu32 SMIWriteAddr;      /* SMI write address global address */
  extern vu32 SMIReadAddr;       /* SMI read address global address */
  extern u32 WaveDataLength;     /* Wave player global data length */
  extern u32 RecordDataLength;   /* Voice recorder global data length */
  extern vu32 RecordStatus;      /* Voice recorder global Status */
  extern vu32 WaveCounter ;      /* Wave player and voice recorder global index */
  vu32 BoardSelfTestStatus = 0;  /* Board Self Test starting status */
  vu32 BoardSelfTestDone = 0;    /* Board test global status */

  /* Board tests results table */
  TestStatus test_result[NumberOfTests] = {FAILED, FAILED, FAILED, FAILED, FAILED,
                                           FAILED, FAILED, FAILED, FAILED, FAILED};
  /* Board failed tests names */
  string BoardSelfTestFailedmsg[NumberOfTests];
  /* Board tests names table */
  string BoardSelfTestmsg[NumberOfTests]={" PushButtons Test ",
                                          "  JoyStick Test   ",
                                          "    Leds Test     ",
                                          " MIC Speaker Test ",
                                          " VarResistor Test ",
                                          "   OSC32K Test    ",
                                          "    OSC4M Test    ",
                                          "  SMI Flash Test  ",
                                          " UART0 UART1 Test ",
                                          " UART1 UART2 Test " };

  u8 Tx_UARTmsg[16] = "MB469 UART Test ";  /* UART transmit message test buffer  */
  u8 Rx_msg1[16];   /* UART receive message test buffer1 */
  u8 Rx_msg2[16];   /* UART receive message test buffer2 */

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/*******************************************************************************
* Function Name  : BoardSelfTest
* Description    : Execute the different board tests.
* Input          : None
* Output         : BoardSelfTestDone: this variable is set to indicate that the
*                  board test was done.
* Return         : None
*******************************************************************************/
void BoardSelfTest(void)
{
  u8 i = 0;

  /* Board Self Test started */
  BoardSelfTestStatus = 1;

  /* Reset LedShowStatus to stop leds toggling when start board test */
  LedShow(DISABLE);
  /* Turn off the four leds */
  GPIO_WriteBit(GPIO1, GPIO_Pin_1, Bit_SET);
  GPIO_WriteBit(GPIO0, GPIO_Pin_16, Bit_SET);
  GPIO_WriteBit(GPIO2, GPIO_Pin_18, Bit_SET);
  GPIO_WriteBit(GPIO2, GPIO_Pin_19, Bit_SET);

  /* Store the PushButtons Test result */
  test_result[i++] = PushButtons_Test();
  /* Store the JoyStick Test result */
  test_result[i++] = JoyStick_Test();
  /* Store the Leds Test result */
  test_result[i++] = Leds_Test();
  /* Store the MIC Speaker Test result */
  test_result[i++] = MIC_Speaker_Test();
  /* Store the VarResistor Test result */
  test_result[i++] = VarResistor_Test();
  /* Store the OSC32K Test result */
  test_result[i++] = OSC32K_Test();
  /* Store the OSC4M Test result */
  test_result[i++] = OSC4M_Test();
  /* Store the SMI Flash Test result */
  test_result[i++] = SMI_Flash_Test();
  /* Store the UART0 to UART1 Test result */
  test_result[i++] = UART0_UART1_Test();
  /* Store the UART1 to UART2 Test result */
  test_result[i++] = UART1_UART2_Test();

  /* Set BoardSelfTestDone to indicate the end of Board test */
  BoardSelfTestDone = 1;

  /* Board Self Test finished */
  BoardSelfTestStatus = 0;

  /* Set LedShowStatus to restart leds toggling at the end of board test */
  LedShow(ENABLE);

  /* Execute UpDownFunc function to dispaly the upper menu */
  UpDownFunc();
  /* Simulate "LEFT" pushbutton press to show TestReport menu on LCD */
  LeftFunc();
}

/*******************************************************************************
* Function Name  : TestReport
* Description    : Presents the failed and passed board tests report.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void TestReport(void)
{
  u8 i = 0, TestFailedCount = 0, Count = 0;
  u8 MyKey = 0;

  /* If the board test is terminated */
  if(BoardSelfTestDone == 1)
  {
    /* Clear all LCD */
    LCD_Clear();
    /* Display "  Overall test  " message in Line1 */
    LCD_DisplayString(Line1, Overalltestmsg, BlackText);
    /* Store failed board tests names in BoardSelfTestFailedmsg buffer */
    for(i = 0; i < 10; i++)
    {
      if(test_result[i] == FAILED)
      {
        BoardSelfTestFailedmsg[TestFailedCount++] = BoardSelfTestmsg[i];
      }
    }
    /* If there are no failed board tests */
    if(TestFailedCount == 0)
    {
      /* Display "  ***Passed***  " message */
      LCD_DisplayString(Line2, Passedmsg, BlackText);
      /* Wait any press on "UP" or "DOWN" pushbuttons */
      while((ReadKey() & UP) != UP);
      /* Execute UpDownFunc function to dispaly the upper menu */
      UpDownFunc();
    }
    /* If there are some failed board tests */
    else
    {
      /* Display "  !!!Failed!!!  " message */
      LCD_DisplayString(Line2, Failedmsg, BlackText);
      /* Wait to not detect "SEL" twice */
      Delay(0xFFFFF);
      /* Wait any press on "SEL" pushbutton */
      while(ReadKey() != SEL);
      /* Display the number of failed tests */
      LCD_Printf(" %d Tests Failed  ", TestFailedCount);
      /* Display "    Press ^SEL^ " */
      LCD_DisplayString(Line2, SELmsg, BlackText);
      /* Wait any press on "SEL" pushbutton */
      while(ReadKey() != SEL);
      /* Clear all LCD */
      LCD_Clear();
      /* Display the first filed board test names */
      LCD_DisplayString(Line1, BoardSelfTestFailedmsg[Count], BlackText);

      /* Loop until any press on "UP" or "DOWN" pushbuttons */
      while(1)
      {
        /* Check which key is pressed */
      	MyKey = ReadKey();
        /* If "RIGHT" pushbutton is pressed */
        if(MyKey == RIGHT)
        {
          /* Select the next failed board test index */
          if(Count >= (TestFailedCount-1))
          {
            Count = 0;
          }
          else
          {
            Count++;
          }
        }
        /* If "RIGHT" pushbutton is pressed */
        else if(MyKey == LEFT)
        {
          /* Select the previous failed board test index */
          if(Count >0)
          {
            Count--;
          }
          else
          {
            Count = TestFailedCount - 1;
          }
        }
        /* If one of "UP" or "DOWN" pushbuttons is pressed */
        else if((MyKey == UP) || (MyKey == DOWN))
        {
          /* Execute UpDownFunc function to dispaly the upper menu */
          UpDownFunc();
          /* Exit the loop */
          return;
        }
      /* Display the failed test board name corresponding to the current index */
      LCD_DisplayString(Line1, BoardSelfTestFailedmsg[Count], BlackText);
      /* Dispaly "  Exit UP/Down " message */
      LCD_DisplayString(Line2,"  Exit UP/Down ", BlackText);
      }
    }
  }
  /* If the board test is not done yet */
  else
  {
    /* Clear all LCD */
    LCD_Clear();
    /* Wait a press of "UP" or "DOWN" key to exit the test report menu */
    while((ReadKey() & UP) != UP)
    {
      /* Display " Board test not  " message on line1 */
      LCD_DisplayString(Line1,Bordtestnotdonemsg1, BlackText);
      /* Display "   done yet!!!   " message on line2 */
      LCD_DisplayString(Line2,Bordtestnotdonemsg2, BlackText);
    }
    /* Execute UpDownFunc function to dispaly the upper menu */
    UpDownFunc();
  }
}

/*******************************************************************************
* Function Name  : msgcmp
* Description    : Compares Tx_msg and Rx_msg1 buffers values.
* Input          : - Tx_msg: first buffer to be compared
*                  - Rx_msg1: second buffer to be compared.
*                  - msglength: buffer's length
* Output         : None
* Return         : PASSED: Tx_msg identical to Rx_msg1
*                  FAILED: Tx_msg differs from Rx_msg1
*******************************************************************************/
TestStatus msgcmp(u8* Tx_msg, u8* Rx_msg1, u16 msglength)
{
  TestStatus Status = PASSED;

  /* Compare each members of both buffers */
  while((msglength--) && (Status == PASSED))
  {
    if(*Tx_msg != *Rx_msg1)
    {
      Status = FAILED;
    }
    Tx_msg++;
    Rx_msg1++;
  }

  /* Display "    Press ^SEL^ " */
  LCD_DisplayString(Line2, SELmsg, BlackText);
  /* Switch the compare test result display "FAIL" or "SUCCESS" */
  if(Status == FAILED)
  {
    /* Wait any press on "SEL" pushbutton */
    while(ReadKey() != SEL)
    {
      LCD_DisplayString(Line1, "     FAIL!!!     ", BlackText);
    }
  }
  else
  {
    /* Wait any press on "SEL" pushbutton */
    while(ReadKey() != SEL)
    {
      LCD_DisplayString(Line1, "   SUCCESS!!!    ", BlackText);
    }
  }
  /* Return the compare test Status */
  return Status;
}

/*******************************************************************************
* Function Name  : IsTestOk
* Description    : Checks whether an elementary test is passed or not.
* Input          : None
* Output         : None
* Return         : PASSED: test passed
*                  FAILED: test failed
*******************************************************************************/
TestStatus IsTestOk(void)
{
  u8 MyKey = 0;

  /* Display  "  ^SEL^ : Passed " */
  LCD_DisplayString(Line1, Passmsg, BlackText);
  /* Display  "  ^LEFT^ : Failed" */
  LCD_DisplayString(Line2, Failmsg, BlackText);

  /* Loop until any press on "SEL" or "LEFT" pushbuttons */
  while(1)
  {
    /* Check which key is pressed */
    MyKey = ReadKey();
    /* If "SEL" pushbutton is pressed */
    if(MyKey == SEL)
    {
      /* Display  "  ^SEL^ : Passed " */
      LCD_DisplayString(Line1, Passmsg, WhiteText);
      /* Display  "  ^LEFT^: Failed" */
      LCD_DisplayString(Line2, Failmsg, BlackText);
      Delay(0x7FFFF);
      /* Return "PASSED" */
      return PASSED;
    }
    /* If "LEFT" pushbutton is pressed */
    else if(MyKey == LEFT)
    {
      /* Display  "  ^SEL^ : Passed " */
      LCD_DisplayString(Line1, Passmsg, BlackText);
      /* Display  "  ^LEFT^: Failed" */
      LCD_DisplayString(Line2, Failmsg, WhiteText);
      Delay(0x7FFFF);
      /* Return "FAILED" */
      return FAILED;
    }
  }
}

/*******************************************************************************
* Function Name  : PushButtons_Test
* Description    : Tests pushbuttons (Wake-up & Key).
* Input          : None
* Output         : None
* Return         : PASSED: test passed
*******************************************************************************/
TestStatus PushButtons_Test(void)
{
  /* Display the test name "PushButtons Test" */
  LCD_DisplayString(Line1, BoardSelfTestmsg[0], WhiteText);

  /* Test on "WAKE-UP" push button */
  LCD_DisplayString(Line2, WAKEUPmsg, BlackText);
  while(GPIO_ReadBit(GPIO1,GPIO_Pin_15) == Bit_RESET);
  while(GPIO_ReadBit(GPIO1,GPIO_Pin_15) != Bit_RESET);

  /* Test on "KEY" push button */
  LCD_DisplayString(Line2, KEYmsg, BlackText);
  while(GPIO_ReadBit(GPIO1,GPIO_Pin_5) == Bit_RESET);
  while(GPIO_ReadBit(GPIO1,GPIO_Pin_5) != Bit_RESET);

  return PASSED;
}

/*******************************************************************************
* Function Name  : JoyStick_Test
* Description    : Tests JoyStick pushbuttons.
* Input          : None
* Output         : None
* Return         : PASSED: test passed
*******************************************************************************/
TestStatus JoyStick_Test(void)
{
  /* Display the test name "  JoyStick Test   " */
  LCD_DisplayString(Line1, BoardSelfTestmsg[1], WhiteText);

  /* Test on "SEL" push button */
  LCD_DisplayString(Line2, SELmsg, BlackText);
  while(GPIO_ReadBit(GPIO0,GPIO_Pin_2) == Bit_RESET);
  while(GPIO_ReadBit(GPIO0,GPIO_Pin_2) != Bit_RESET);

  /* Test on "RIGHT" push button */
  LCD_DisplayString(Line2, RIGHTmsg, BlackText);
  while(GPIO_ReadBit(GPIO1,GPIO_Pin_13) == Bit_RESET);
  while(GPIO_ReadBit(GPIO1,GPIO_Pin_13) != Bit_RESET);

  /* Test on "LEFT" push button */
  LCD_DisplayString(Line2, LEFTmsg, BlackText);
  while(GPIO_ReadBit(GPIO1,GPIO_Pin_12) == Bit_RESET);
  while(GPIO_ReadBit(GPIO1,GPIO_Pin_12) != Bit_RESET);

  /* Test on "UP" push button */
  LCD_DisplayString(Line2, UPmsg, BlackText);
  while(GPIO_ReadBit(GPIO0,GPIO_Pin_8) == Bit_RESET);
  while(GPIO_ReadBit(GPIO0,GPIO_Pin_8) != Bit_RESET);

  /* Test on "DOWN" push button */
  LCD_DisplayString(Line2, DOWNmsg, BlackText);
  while(GPIO_ReadBit(GPIO1,GPIO_Pin_7) == Bit_RESET);
  while(GPIO_ReadBit(GPIO1,GPIO_Pin_7) != Bit_RESET);

  return PASSED;
}

/*******************************************************************************
* Function Name  : Leds_Test
* Description    : Performs a successive lighting of the four red leds.
* Input          : None
* Output         : None
* Return         : PASSED: test passed
*                  FAILED: test failed
*******************************************************************************/
TestStatus Leds_Test(void)
{
  /* Display the test name "    Leds Test     " */
  LCD_DisplayString(Line1, BoardSelfTestmsg[2], WhiteText);

  /* Display  "Press ^SEL^ " */
  LCD_DisplayString(Line2, SELmsg, BlackText);

  /* Loop until SEL key pressed */
  while(ReadKey() != SEL)
  {
    LedShow(ENABLE);
  }
  /* Disable leds toggling after press on "SEL" */
  LedShow(DISABLE);
  /* Turn off the four leds */
  GPIO_WriteBit(GPIO1, GPIO_Pin_1, Bit_SET);
  GPIO_WriteBit(GPIO0, GPIO_Pin_16, Bit_SET);
  GPIO_WriteBit(GPIO2, GPIO_Pin_18, Bit_SET);
  GPIO_WriteBit(GPIO2, GPIO_Pin_19, Bit_SET);

  /* Return the test result */
  return IsTestOk();
}

/*******************************************************************************
* Function Name  : MIC_Speaker_Test
* Description    : Performs a record then a play of a test wave.
* Input          : None
* Output         : None
* Return         : PASSED: test passed
*                  FAILED: test failed
*******************************************************************************/
TestStatus MIC_Speaker_Test(void)
{
  u32 SavedRecordDataLength = 0;

  SavedRecordDataLength = RecordDataLength;
  /* Display the test name " MIC Speaker Test " */
  LCD_DisplayString(Line1, BoardSelfTestmsg[3], WhiteText);

  /* Display  "Press ^SEL^ " */
  LCD_DisplayString(Line2, SELmsg, BlackText);
  /* Loop until "SEL" key pressed */
  while(ReadKey() != SEL);

  /* Set RecordStatus to start recording phase */
  RecordStatus = 1;
  /* SMI Configuration */
  SMI_FLASH_Init();
  /* Set SMI write address to the address dedivcated for board test recording */
  SMIWriteAddr = BoardTestReadWriteAddr;

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
  /* Disable RTC Alarm interrupt during SMI erasing */
  RTC_ITConfig(RTC_IT_Alarm, DISABLE);

  /* Display SMI erasing message */
  LCD_DisplayString(Line2, "Wait SMI erasing", BlackText);
  /* Erase SMI sector to store voice recording data */
  SMI_FLASH_SectorErase(TestBoardSector);
  /* Display "Record:Press KEY" message to start voice recording */
  LCD_DisplayString(Line2, "Record:Press KEY", BlackText);
  /* Reset VoiceRecord for board voice test playing */
  VoiceRecord = 0;
  /* Reset SelectedWave for board voice test playing */
  SelectedWave = 0;
  /* Enable EXTIT for "Key" pushbutton */
  KeyButtonOn();
  /* Play Alarm if it was happen during the SMI erasing */
  if(RTC_GetFlagStatus(RTC_FLAG_Alarm) != RESET)
  {
    /* Start Alarm playing */
    WavePlayerAlarm_Start();
  }

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
  /* Clear RTC Alarm interrupt pending bit*/
  RTC_ClearITPendingBit(RTC_IT_Alarm);
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
  /* Enable RTC Alarm interrupt */
  RTC_ITConfig(RTC_IT_Alarm, ENABLE);

  /* Wait a press on "UP" or "DOWN" pushbuttons: start wave player phase */
  while((ReadKey() & UP) != UP);
  /* Set SMI start read address to the first board test wave data */
  SMIReadAddr = BoardTestReadWriteAddr;
  /* Set WaveDataLenght to the board testrecorded wave length */
  WaveDataLength = RecordDataLength;
  /* Restore the voice record data length */
  RecordDataLength = SavedRecordDataLength;

  /* Configure P1.2 as alternate function (TIM2_OC2) */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_Init(GPIO1, &GPIO_InitStructure);


  /* Set TIM0 period to 22050 Hz */
  TIM_SetPeriod(TIM0, 0x1C6);

  /* Start TIM2 */
  TIM_Cmd(TIM2, ENABLE);
  /* Enable TIM0 update interrupt */
  TIM_ITConfig(TIM0, TIM_IT_Update, ENABLE);
  /* Start TIM0 */
  TIM_Cmd(TIM0, ENABLE);
  /* Wait a press on "UP" or "DOWN" pushbuttons */
  while((ReadKey() & UP) != UP)
  {
    /* Display the test name "MIC Speaker Test" */
    LCD_DisplayString(Line1, BoardSelfTestmsg[3], WhiteText);
    /* Display message to start test wave playing */
    LCD_DisplayString(Line2, "Skip test:UP/DOWN", BlackText);
  }
  /* Stop wave player phase */
  WavePlayer_Stop();

  /* Disable ScreenSaver */
  ScreenSaver_Cmd(DISABLE);
  /* Return the test result */
  return IsTestOk();
}

/*******************************************************************************
* Function Name  : VarResistor_Test
* Description    : Turns on/off the four red leds according to the converted
*                  value of ADC Channel3 input voltage.
* Input          : None
* Output         : None
* Return         : PASSED: test passed
*                  FAILED: test failed
*******************************************************************************/
TestStatus VarResistor_Test(void)
{
  u32 val = 0;

  /* ADC Channel3 (P0.17) configuration */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_17 ;
  GPIO_Init(GPIO0, &GPIO_InitStructure);

  /* ADC configuration */
  ADC_InitStructure.ADC_FirstChannel = ADC_CHANNEL3;
  ADC_Init(&ADC_InitStructure);
  /* Start conversion */
  ADC_ConversionCmd(ADC_Conversion_Start);

  /* Display the test name " VarResistor Test " */
  LCD_DisplayString(Line1, BoardSelfTestmsg[4], WhiteText);

  /* Display  "Press ^SEL^ " */
  LCD_DisplayString(Line2, SELmsg, BlackText);
  /* Loop until "SEL" key pressed */
  while (ReadKey() != SEL);
  /* Display "Turn the Potentiometer & Press SEL" message */
  LCD_Printf("Turn the Potentiometer & Press SEL");
  /* Loop until SEL key pressed */
  while (ReadKey() != SEL)
  {
    /* Get the Channel3 converted value */
    val = ADC_GetConversionValue(ADC_CHANNEL3);
    /* Switch Channel3 converted value turn on the leds */
    if (val > 0x00000300)
    {
      /* Turn on the four leds LD2 - LD5 */
      GPIO_WriteBit(GPIO1,GPIO_Pin_1, Bit_RESET);
      GPIO_WriteBit(GPIO0,GPIO_Pin_16, Bit_RESET);
      GPIO_WriteBit(GPIO2,GPIO_Pin_18, Bit_RESET);
      GPIO_WriteBit(GPIO2,GPIO_Pin_19, Bit_RESET);
    }

    else if (val > 0x00000200)
    {
      /* LD2, LD3 and LD4 on , LD5 off */
      GPIO_WriteBit(GPIO1,GPIO_Pin_1, Bit_RESET);
      GPIO_WriteBit(GPIO0,GPIO_Pin_16, Bit_RESET);
      GPIO_WriteBit(GPIO2,GPIO_Pin_18, Bit_RESET);
      GPIO_WriteBit(GPIO2,GPIO_Pin_19, Bit_SET);
    }
    else if (val > 0x00000100)
    {
      /* LD2, LD3 are on  and LD4, LD5 are off */
      GPIO_WriteBit(GPIO1,GPIO_Pin_1, Bit_RESET);
      GPIO_WriteBit(GPIO0,GPIO_Pin_16, Bit_RESET);
      GPIO_WriteBit(GPIO2,GPIO_Pin_18, Bit_SET);
      GPIO_WriteBit(GPIO2,GPIO_Pin_19, Bit_SET);
    }
    else
    {
      /* LD2 is on , LD3, LD4 and LD5 are off */
      GPIO_WriteBit(GPIO1,GPIO_Pin_1, Bit_RESET);
      GPIO_WriteBit(GPIO0,GPIO_Pin_16, Bit_SET);
      GPIO_WriteBit(GPIO2,GPIO_Pin_18, Bit_SET);
      GPIO_WriteBit(GPIO2,GPIO_Pin_19, Bit_SET);
    }
  }
  /* Turn off the four leds */
  GPIO_WriteBit(GPIO1, GPIO_Pin_1, Bit_SET);
  GPIO_WriteBit(GPIO0, GPIO_Pin_16, Bit_SET);
  GPIO_WriteBit(GPIO2, GPIO_Pin_18, Bit_SET);
  GPIO_WriteBit(GPIO2, GPIO_Pin_19, Bit_SET);

  /* Stop the ADC conversion */
  ADC_ConversionCmd(ADC_Conversion_Stop);
  /* Test on the ADC START bit: ADC stopped */
  while(ADC_GetSTARTBitStatus());
  /* restore the previous ADC configuration */
  ADC_InitStructure.ADC_FirstChannel = ADC_CHANNEL15;
  ADC_Init(&ADC_InitStructure);

  /* Return the test result */
  return IsTestOk();
}

/*******************************************************************************
* Function Name  : OSC32K_Test
* Description    : Check if the 32KHz Oscillator is ready or not.
* Input          : None
* Output         : None
* Return         : PASSED: test passed
*                  FAILED: test failed
*******************************************************************************/
TestStatus OSC32K_Test(void)
{
  u32 nCount = 0;
  FlagStatus OSC32KStatus = RESET;

  /* Display the test name "OSC32K Test" */
  LCD_DisplayString(Line1, BoardSelfTestmsg[5], WhiteText);

  /* If the 32KHz Oscillator is ready */
  if(MRCC_GetFlagStatus(MRCC_FLAG_OSC32KRDY) != RESET)
  {
    OSC32KStatus = SET;
  }
  /* If the 32KHz Oscillator is not ready */
  else
  {
    /* Enable OSC32K */
    MRCC_OSC32KConfig(MRCC_OSC32K_Enable, MRCC_OSC32KBypass_Disable);
    /* Test on the "OSC32KRDY" flag after enabling the 32KHz Oscillator*/
    for(nCount = 0xFFFF; nCount != 0; nCount--)
    {
      if(MRCC_GetFlagStatus(MRCC_FLAG_OSC32KRDY) != RESET)
      {
        OSC32KStatus = SET;
        nCount = 0;
      }
    }
  }

  /* Display  "Press ^SEL^ " */
  LCD_DisplayString(Line2, SELmsg, BlackText);
  /* Loop until "SEL" key pressed */
  while(ReadKey() != SEL);

  /* If the 32KHz Oscillator is operational */
  if(OSC32KStatus == SET)
  {
    /* Loop until SEL key pressed */
    while(ReadKey() != SEL)
    {
      LCD_DisplayString(Line1, "   SUCCESS!!!    ", BlackText);
    }
    /* Return the test result "PASSED"*/
    return PASSED;
  }
  /* If the 32KHz Oscillator is invalid */
  else
  {
     /* Loop until SEL key pressed */
    while(ReadKey() != SEL)
    {
      LCD_DisplayString(Line1, "     FAIL!!!     ", BlackText);
    }
    /* Return the test result "FAILED"*/
    return FAILED;
  }
}

/*******************************************************************************
* Function Name  : OSC4M_Test
* Description    : Checks if the 4M Oscillator is present or not.
* Input          : None
* Output         : None
* Return         : PASSED: test passed
*                  FAILED: test failed
*******************************************************************************/
TestStatus OSC4M_Test(void)
{
  /* Display the test name "OSC4M Test" */
  LCD_DisplayString(Line1, BoardSelfTestmsg[6], WhiteText);

  /* Clear NCKDF bit */
  MRCC_ClearFlag(MRCC_FLAG_NCKD);

  /* Display  "Press ^SEL^ " */
  LCD_DisplayString(Line2, SELmsg, BlackText);
  /* Loop until SEL key pressed */
  while(ReadKey() != SEL);

  /* If the OSC4M is invalid */
  if(MRCC_GetFlagStatus(MRCC_FLAG_NCKD) != RESET)
  {
    /* Loop until SEL key pressed */
    while(ReadKey() != SEL)
    {
      LCD_DisplayString(Line1, "     FAIL!!!     ", BlackText);
    }
    /* Return the test result "FAILED"*/
    return FAILED;
  }
  /* If the OSC4M is operational */
  else
  {
    /* Loop until SEL key pressed */
    while(ReadKey() != SEL)
    {
      LCD_DisplayString(Line1, "   SUCCESS!!!    ", BlackText);
    }
    /* Return the test result "PASSED"*/
    return PASSED;
  }
}

/*******************************************************************************
* Function Name  : SMI_Flash_Test
* Description    : Check if the SMI Flash is accessible or not by reading its ID.
* Input          : None
* Output         : None
* Return         : PASSED: test passed
*                  FAILED: test failed
*******************************************************************************/
TestStatus SMI_Flash_Test(void)
{
  /* Display the test name "SMI Flash Test" */
  LCD_DisplayString(Line1, BoardSelfTestmsg[7], WhiteText);

  /* Initialize the SMI Flash */
  SMI_FLASH_Init();

  /* Display  "Press ^SEL^ " */
  LCD_DisplayString(Line2, SELmsg, BlackText);
  /* Loop until SEL key pressed */
  while(ReadKey() != SEL);

  /* If the SMI ID is correct */
  if(SMI_FLASH_ReadID() != M25P64_ID)
  {
    /* Loop until SEL key pressed */
    while(ReadKey() != SEL)
    {
      LCD_DisplayString(Line1, "     FAIL!!!     ", BlackText);
    }
    /* Return the test result "FAILED"*/
    return FAILED;
  }
  /* If the SMI ID is incorrect */
  else
  {
    /* Loop until SEL key pressed */
    while(ReadKey() != SEL)
    {
      LCD_DisplayString(Line1, "   SUCCESS!!!    ", BlackText);
    }
    /* Return the test result "PASSED"*/
    return PASSED;
  }
}

/*******************************************************************************
* Function Name  : UART0_UART1_Test
* Description    : Performs a transfer of 16 bytes buffer between UART0 and UART1
* Input          : None
* Output         : None
* Return         : PASSED: test passed
*                  FAILED: test failed
*******************************************************************************/
TestStatus UART0_UART1_Test(void)
{
  u8 TxCounter = 0, RxCounter = 0;

  /* Enable the UART0 and UART1 Clocks */
  MRCC_PeripheralClockConfig(MRCC_Peripheral_UART0 | MRCC_Peripheral_UART1, ENABLE);
  /* Configure the UART0_Tx and UART1_Tx as alternate function */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_11 | GPIO_Pin_21;
  GPIO_Init(GPIO0, &GPIO_InitStructure);
  /* Configure the UART0_Rx and UART1_Rx as input floating */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10  | GPIO_Pin_20;
  GPIO_Init(GPIO0, &GPIO_InitStructure);
  /* Configure the UART0 and the UART1 */
  UART_InitStructure.UART_WordLength = UART_WordLength_8D;
  UART_InitStructure.UART_StopBits = UART_StopBits_1;
  UART_InitStructure.UART_Parity = UART_Parity_Odd ;
  UART_InitStructure.UART_BaudRate = 9600;
  UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
  UART_InitStructure.UART_Mode = UART_Mode_Tx_Rx;
  UART_InitStructure.UART_TxFIFOLevel = UART_FIFOLevel_1_2; /* FIFO size 16 bytes, FIFO level 8 bytes */
  UART_InitStructure.UART_RxFIFOLevel = UART_FIFOLevel_1_2; /* FIFO size 16 bytes, FIFO level 8 bytes */
  UART_Init(UART0, &UART_InitStructure);
  UART_Init(UART1, &UART_InitStructure);
  /* Enable the UART0 */
  UART_Cmd(UART0, ENABLE);
  /* Enable the UART1 */
  UART_Cmd(UART1, ENABLE);

  /* Display the test name "UART0 UART1 Test" */
  LCD_DisplayString(Line1, BoardSelfTestmsg[8], WhiteText);
  /* Display  "Press ^SEL^ " */
  LCD_DisplayString(Line2, SELmsg, BlackText);
  /* Loop until SEL key pressed */
  while(ReadKey() != SEL);
  /* Display the hardware connection message */
  LCD_DisplayString(Line1, "Connect CN4 to   ", BlackText);
  LCD_DisplayString(Line2, "CN8 & Press SEL  ", BlackText);

  /* Loop until SEL key pressed */
  while(ReadKey() != SEL);
  /* Transfer data between UART0 and UART1 sequence */
  while(TxCounter < 16)
  {
    /* Send one byte from UART0 to UART1 */
    UART_SendData(UART0, Tx_UARTmsg[TxCounter++]);
    /* Loop until the end of transmit */
    while(UART_GetFlagStatus(UART0,UART_FLAG_Busy)!= RESET);
    /* Read when the Rx FIFO is not empty */
    while(UART_GetFlagStatus(UART1,UART_FLAG_RxFIFOEmpty) == RESET)
    {
      /* Store the received byte in Rx_msg1 buffer */
      Rx_msg1[RxCounter++] = UART_ReceiveData(UART1);
    }
  }

  /* Compare the send and received strings: return the test result */
  return(msgcmp(Tx_UARTmsg, Rx_msg1, 16));
}

/*******************************************************************************
* Function Name  : UART1_UART2_Test
* Description    : Performs a transfer of 16 bytes buffer between UART1 and UART2
* Input          : None
* Output         : None
* Return         : PASSED: test passed
*                  FAILED: test failed
*******************************************************************************/
TestStatus UART1_UART2_Test(void)
{
  u8 TxCounter = 0, RxCounter = 0;

  /* Enable the UART1 and UART2 Clocks */
  MRCC_PeripheralClockConfig(MRCC_Peripheral_UART1 | MRCC_Peripheral_UART2, ENABLE);
  /* Configure the UART1_Tx and UART2_Tx and UART1_Rx as alternate function */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_20 | GPIO_Pin_21 | GPIO_Pin_25;
  GPIO_Init(GPIO0, &GPIO_InitStructure);
  /* Configure the UART2_Rx  as input floating */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_24;
  GPIO_Init(GPIO0, &GPIO_InitStructure);
  /* Configure the UART1 and the UART2 */
  UART_InitStructure.UART_WordLength = UART_WordLength_8D;
  UART_InitStructure.UART_StopBits = UART_StopBits_1;
  UART_InitStructure.UART_Parity = UART_Parity_Odd ;
  UART_InitStructure.UART_BaudRate = 9600;
  UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
  UART_InitStructure.UART_Mode = UART_Mode_Tx_Rx;
  UART_InitStructure.UART_TxFIFOLevel = UART_FIFOLevel_1_2; /* FIFO size 16 bytes, FIFO level 8 bytes */
  UART_InitStructure.UART_RxFIFOLevel = UART_FIFOLevel_1_2; /* FIFO size 16 bytes, FIFO level 8 bytes */
  UART_Init(UART1, &UART_InitStructure);
  UART_Init(UART2, &UART_InitStructure);
  /* Enable the UART1 */
  UART_Cmd(UART1, ENABLE);
  /* Enable the UART2 */
  UART_Cmd(UART2, ENABLE);

  /* Display the test name "UART1 UART2 Test" */
  LCD_DisplayString(Line1, BoardSelfTestmsg[9], WhiteText);
  /* Display  "Press ^SEL^ " */
  LCD_DisplayString(Line2, SELmsg, BlackText);
  /* Loop until SEL key pressed */
  while(ReadKey() != SEL);
  /* Display the hardware connection message */
  LCD_DisplayString(Line1, "Connect CN8 to   ", BlackText);
  LCD_DisplayString(Line2, "CN10 & Press SEL ", BlackText);

  /* Loop until SEL key pressed */
  while(ReadKey() != SEL);
  /* Transfer data between UART1 and UART2 sequence */
  while(TxCounter < 16)
  {
    /* Send one byte from UART1 to UART2 */
    UART_SendData(UART1, Tx_UARTmsg[TxCounter++]);
    /* Loop until the end of transmit */
    while(UART_GetFlagStatus(UART1,UART_FLAG_Busy)!= RESET);
    /* Read when the Rx FIFO is not empty */
    while(UART_GetFlagStatus(UART2,UART_FLAG_RxFIFOEmpty) == RESET)
    {
      /* Store the received byte in Rx_msg2 buffer */
      Rx_msg2[RxCounter++] = UART_ReceiveData(UART2);
    }
  }

  /* Compare the send and received strings: return the test result */
  return(msgcmp(Tx_UARTmsg, Rx_msg2, 16));
}

/******************* (C) COPYRIGHT 2006 STMicroelectronics *****END OF FILE****/
