/**
  ******************************************************************************
  * @file 3rd_CEC_Device/src/main.c 
  * @author  MCD Application Team
  * @version  V2.0.0
  * @date  04/27/2009
  * @brief  Main program body
  ******************************************************************************
  * @copy
  *
  * THE PRESENT FIRMWARE 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 FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2009 STMicroelectronics</center></h2>
  */ 


/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_cec.h"
#include "stm3210b_lcd.h"


/** @addtogroup 3rd_CEC_Device
  * @{
  */ 


/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define Column0        320
#define Column1        304
#define Column2        288
#define Column3        272
#define Column4        256
#define Column5        240
#define Column6        224
#define Column7        208
#define Column8        192
#define Column9        176
#define Column10       160
#define Column11       144
#define Column12       128
#define Column13       112
#define Column14        96
#define Column15        80
#define Column16        64
#define Column17        48
#define Column18        32
#define Column19        16
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
extern uint8_t ReceiveBuffer[10];
uint8_t ReceivedFrame = 0;
uint8_t SendFrame = 0;
uint32_t ReceiveInfos = 0;
extern ErrorStatus SendStatus;
uint8_t *BufferPointer;
uint8_t ByteNumber = 0;
uint8_t SendTo = 0;

/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void NVIC_Configuration(void);
void EXTI_Configuration(void);
void GPIO_Configuration(void);
void DisplayDataByte (uint8_t Data, uint8_t Line, uint8_t Column);
void DisplayHexToChar (uint8_t Data, uint16_t Line, uint16_t Column);
uint8_t HexToChar(uint8_t Data);
void DisplayBuffer(uint8_t *DataBuffer, uint8_t BufferSize, uint16_t Line);
static LCD_DisplayString(uint8_t Row, uint16_t Column,uint8_t *ptr);

/* Private functions ---------------------------------------------------------*/


/**
  * @brief  Main program.
  * @param  None
  * @retval : None
  */
int main(void)
{


  /* RCC configuration */
  RCC_Configuration();
  
  /* NVIC configuration */
  NVIC_Configuration();

  /* CEC initialization */
  CEC_Init();
    
  /* GPIO configuration */
  GPIO_Configuration();
        
  /* EXTI configuration */
  EXTI_Configuration();
    
  /* LCD initialization */
  STM3210B_LCD_Init();

  /* Clear the LCD */
  LCD_Clear(Blue);

  /* Display initialization */
  LCD_SetTextColor(White);
  LCD_SetBackColor(Black);
  LCD_DisplayString(Line0, Column0, "Receive:");
  LCD_DisplayString(Line6, Column0, "Send to:");
  LCD_SetBackColor(Blue);
  LCD_DisplayString(Line5, Column0, "____________________");

  /* Infinite loop */
  while (1)
  {
    /* If a frame has been received */
    if(ReceivedFrame)
    {
      LCD_SetBackColor(Blue);
      
      /* Check if the frame has been received correctly */
      if(ReceiveInfos & ReceiveFrameStatusMask)
      {
        /* Check if the frame has been sent to me */
        if(ReceiveInfos & FrameSendToMeMask)
        {
          LCD_SetBackColor(Green);
          LCD_DisplayString(Line0, Column10, "Succeeded");  
        }
        else /* The receive was successful, but I'm not the concerned follower */
        {
          LCD_SetBackColor(Magenta);
          LCD_DisplayString(Line0, Column10, "Detected ");  
        }
      }
      else /* The receive was failed */
      {
         LCD_SetBackColor(Red);
         LCD_DisplayString(Line0, Column10, " Failed  ");  
      }
      /* Display the receive status, the initiator address, the received data 
      frame and  the number of received bytes  */
      LCD_SetBackColor(Blue);
      LCD_DisplayString(Line1, Column0, "Sender Address = ");
      DisplayHexToChar ((uint8_t)(ReceiveInfos & InitiatorAddressMask), Line1,Column17);
      LCD_DisplayString(Line2, Column0, "Number of bytes:");
      DisplayHexToChar ((uint8_t)(ReceiveInfos>>8), Line2,Column17);
      DisplayBuffer(ReceiveBuffer,ReceiveInfos>>8, Line3);
      ReceivedFrame=0;
    }
    if (SendFrame)
    {
      /* Check if the frame has been sent successfully */
      if (SendStatus != ERROR ) /* The send succeeded */
      {
        LCD_SetBackColor(Green);
    	LCD_DisplayString(Line7, Column0, "Send Status: Succeed"); 
      } 
      else  /* The send failed */
      {
        LCD_SetBackColor(Red); 
        LCD_DisplayString(Line7, Column0, "Send Status: Fail   "); 
      }
      
      /* Display the data frame to send and the address of the follower */
      LCD_SetBackColor(Blue);
      DisplayBuffer(BufferPointer,ByteNumber , Line8);
      DisplayHexToChar (SendTo, Line6, Column8);
      SendFrame=0;
    }
  }
}



/**
  * @brief  Configures the different system clocks.
  * @param  None
  * @retval : None
  */
void RCC_Configuration(void)
{   
  ErrorStatus HSEStartUpStatus;
  
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);
 
    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 
  
    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1); 

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);

    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

    /* Enable PLL */ 
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }
  
  /* Enable GPIOB (for key button) and GPIOD (for SPI communication of the LCD) clocks */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD , ENABLE);
}



/**
  * @brief  Configures Vector Table base location and NVIC global 
  *   interrupts.
  * @param  None
  * @retval : None
  */
void NVIC_Configuration(void)
{
 NVIC_InitTypeDef NVIC_InitStructure;
  
  
  /* Configure two bits for preemption priority */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* Enable the EXTI9_5 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}



/**
  * @brief  Configures the different GPIO ports.
  * @param  None
  * @retval : None
  */
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
    
  /* Configure GPIOB Pin 9 as input floating (For key button) */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
  /* Connect EXTI Line9 to GPIOB Pin 9 */
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9);
}



/**
  * @brief  Configures the different GPIO ports.
  * @param  None
  * @retval : None
  */
void EXTI_Configuration(void)
{
  EXTI_InitTypeDef EXTI_InitStructure;

  /* Configure EXTI Line9 to generate an interrupt on falling edge */  
  EXTI_InitStructure.EXTI_Line = EXTI_Line9;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
}



/**
  * @brief  Displays the content of a buffer on the LCD in Hex format.
  * @param DataBuffer: a pointer to the buffer to be displayed.
  * @param BufferSize: the size of the buffer in byte.
  * @param Line: the line where the data will be displayed.
  * @retval : None
  */
void DisplayBuffer(uint8_t *DataBuffer, uint8_t BufferSize, uint16_t Line)
{
  uint8_t i;
  uint16_t column = Column5;
  uint16_t line = Line;
 
  LCD_DisplayString(Line, Column0, "                    "); 
  LCD_DisplayString(Line+24, Column0, "                    "); 
  LCD_DisplayString(Line, Column0, "Data:"); 

  for (i=0;i<BufferSize;i++)
  { 
    DisplayHexToChar (*(DataBuffer++), line, column);
    column -=32;
    LCD_DisplayChar (line, column, ',');
   
    if (i==4)
    {
      line += 24;
      column = Column0;
    }
    
    column -=16;
  }
}



/**
  * @brief  Displays a data byte on the LCD in Hex format.
  * @param Data: the data to be displayed.
  * @param Line: the line where the data will be displayed.
  * @param Column: the column where the data will be displayed.
  * @retval : None
  */
void DisplayHexToChar (uint8_t Data, uint16_t Line, uint16_t Column)
{
  LCD_DisplayChar(Line,Column-16,HexToChar(Data));
  LCD_DisplayChar(Line,Column,HexToChar(Data>>4));
}



/**
  * @brief  Converts a data (four bits) to a character to be displayed 
  *   in Hex format.
  * @param Data: byte to be converted.
  * @retval : None
  */
uint8_t HexToChar(uint8_t Data)
{
  Data &= 0xF;
  
  switch(Data)
  {
    case 0xA: return 0x41;
    case 0xB: return 0x42;
    case 0xC: return 0x43;
    case 0xD: return 0x44;
    case 0xE: return 0x45;
    case 0xF: return 0x46;
    default: return (Data+0x30);
  }
}


/**
  * @brief  Displays the string on the required row and column
  *   Input1         : Raw: required row 
  *   Input2         : Column: required Column 
  *   Input2         : ptr: pointer to the string to be displayed
  * @retval : None
  */
static LCD_DisplayString(uint8_t Row, uint16_t Column,uint8_t *ptr)
{
  uint32_t i = 0;
  uint16_t refcolumn = Column;
  /* Send the string character by character on lCD */
  while ( (*ptr !=0) && (i < 20))
  {
    /* Display one character on LCD */
    LCD_DisplayChar(Row, refcolumn, *ptr);
    /* Decrement the column position by 16 */
    refcolumn -= 16;
    /* Point on the next character */
    ptr++;
    /* Increment the character counter */
    i++;
  }
}


/**
  * @brief  Inserts a delay time.
  * @param ount: specifies the delay time length (time base 10 ms).
  * @retval : None
  */
void Delay(uint32_t nCount)
{
  uint32_t n;
  uint32_t counts;
  
  for (counts=0;counts<nCount;counts++)
  {
    for(n=0;n<0x13942 ;n++);
  }
}


#ifdef USE_FULL_ASSERT


/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param file: pointer to the source file name
  * @param line: assert_param error line source number
  * @retval : None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/**
  * @}
  */ 



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