/**
  ******************************************************************************
  * @file    lcd_driver.c
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    07/07/2010
  * @brief   This file includes the TFT-LCD driver for Crystal Display Module 
             CT05350DW0000T.     
  ******************************************************************************
  * @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 2010 STMicroelectronics</center></h2>
  */ 

/* Includes ------------------------------------------------------------------*/
#include "lcd_driver.h"
#include "main.h"
#include "fonts.h"
#include "backlight_control.h"
#include "stm3210e_eval_fsmc_nor.h"
#include "stm3210e_eval_fsmc_sram.h"


/** @defgroup lcd_driver
* @brief This file is the TFT-LCD driver for controller-less TFT LCD 
* @{
*/ 

/** @defgroup lcd_driver_Private_TypesDefinitions
* @{
*/ 
/**
* @}
*/ 


/** @defgroup lcd_driver_Private_Defines
* @{
*/ 

/* LCD-CS is CE4 - Bank 4 of NOR/SRAM Bank 1~4 */
#define LCD_BASE                     ((uint32_t)(0x60000000 | 0x0C000000))

/* Frame Rate control Parameters */
#define FRAME_TIM_PERIOD             (uint32_t) 44999 

/* Slideshow paramters */
#define SLIDESHOW_TIM_PERIOD         (uint32_t) 44999 

/* Bitmpas images address in NOR  */
const uint32_t NORImageFileAddrMap[52] = {
0x64F7FBFA, 0x64D7285E,
0x6461EB7A, 0x646443BC, 0x64669BFE, 0x6468F440, 0x646B4C82,
0x646DA4C4, 0x646FFD06, 0x64725548, 0x6474AD8A, 0x647705CC,
0x64795E0E, 0x647BB650, 0x647E0E92, 0x648066D4, 0x6482BF16,
0x64851758, 0x64876F9A, 0x6489C7DC, 0x648C201E, 0x648E7860,
0x6490D0A2, 0x649328E4, 0x64958126, 0x6497D968, 0x649A31AA,
0x649C89EC, 0x649EE22E, 0x64A13A70, 0x64A392B2, 0x64A5EAF4,
0x64A84336, 0x64AA9B78, 0x64ACF3BA, 0x64AF4BFC, 0x64B1A43E,
0x64B3FC80, 0x64B654C2, 0x64B8AD04, 0x64BB0546, 0x64BD5D88,
0x64BFB5CA, 0x64C20E0C, 0x64C4664E, 0x64C6BE90, 0x64C916D2,
0x64CB6F14, 0x64CDC756, 0x64D01F98, 0x64D277DA, 0x64D4D01C}; 

/**
* @}
*/ 


/** @defgroup lcd_driver_Private_Macros
* @{
*/ 
/**
* @}
*/ 


/** @defgroup lcd_driver_Private_Variables
* @{
*/
__IO uint32_t ImageSourceAddrCounter      = 0;
uint16_t DummyDisplayBuffer[LCD_HORZ_LINE]={0};
__IO uint32_t ImageSourceAddress          = SRAM_IMAGE1;
uint8_t SlidesCheck[2]                    = {0x42, 0x4D};
__IO uint8_t  NOR_ImageIndex              = 0;
__IO uint8_t DMAComplete                  = TRUE;
uint8_t imageTab[2]                       = {0};
NOR_IDTypeDef NOR_ID;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  
/**
* @}
*/ 


  
/** @defgroup lcd_driver_Private_FunctionPrototypes
* @{
*/ 
static uint8_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
static void SlideShow_TimerConfig(void);
static void FrameRate_TimerConfig(void);
static void LCD_SynchSignalConfig(void);
static void LCD_DriverDMAConfig(void);
static void LCD_DriverInterruptConfig(void);
static void SRAM_ImageCopyDMAIntConfig(void);
static void SRAM_ImageCopyWithDMA(uint32_t src_address,uint32_t dest_address);
/**
* @}
*/ 


/** @defgroup lcd_driver_Private_Functions
* @{
*/ 

/**
* @brief  LCD_Init.
*         Intializes LCD hardware and FSMC configuration.
*         Intializes LCD configuration registers
* @param  None
* @retval None
*/
void LCD_Init(void)
{ 
  /* Configure the LCD Control pins--------------------------------------------*/
  LCD_CtrlLinesConfig();
  
  /* Configure the SPI1 interface----------------------------------------------*/
  LCD_SPIConfig();
  
  /* Configure the FSMC interface ---------------------------------------------*/
  LCD_FSMCConfig();
  
  /* Configure LCD registers -------------------------------------------------*/
  /* Register settings are for display window & synchronisation signal settings */
  LCD_WriteReg(LCD_R01, 0x2300); 
  Delay(10);   
  LCD_WriteReg(LCD_R05, 0xA304); 
  Delay(10);     
  LCD_WriteReg(LCD_R17, 0x0482); 
  Delay(10); 
  
}

/**
* @brief  LCD_AgingModeDisplay
*         Test mode for LCD .In case, HSYNC and VSYNC are not available and
*         only clock signal is given to LCD, then LCD shows color change 
* @param  None
* @retval None
*/
void LCD_AgingModeDisplay(void)
{
  /* Put data zero on data bus */
  while(1)
  {    
    *(vu16 *)(LCD_BASE) = 0x00;   
  } 
}


/**
* @brief  LCD_WriteReg.
*         Write LCD register using SPI interface to LCD
* @param  LCD_Reg: address of the selected register.
*         LCD_RegValue: value to write to the selected register.
* @retval None
*/
void LCD_WriteReg(uint8_t LCD_Reg, uint16_t LCD_RegValue)
{
  uint8_t reg_value_MSB= 0;
  uint8_t reg_value_LSB= 0;
  
  reg_value_LSB = LCD_RegValue & 0x00FF;
  reg_value_MSB = LCD_RegValue >> 8;
  
  /*-----------------Start -- Send the Address of the Register ---------------*/  
  SPI_TFT_CS_LOW();
  
  /*Send the Index Data - 8 bit*/
  SPI_I2S_SendData(SPI1, INDEX_DATA1);
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
  {
  }
  
  /*Send the Register Address 16 bit*/
  SPI_I2S_SendData(SPI1, 0x00);
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
  {
  }
  SPI_I2S_SendData(SPI1, LCD_Reg);
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
  {
  }
  
  /*Delay required for proper Chip Select Timing*/
  Delay(1); 
  
  /*High the Chip Select*/
  SPI_TFT_CS_HIGH();
  
  
  /*Delay required for proper Chip Select Timing*/
  Delay(10); 
  
  /*-----------------Start -- Send the Value to the Register ----------------*/  
  /*Low the Chip Select*/
  SPI_TFT_CS_LOW();
  
  /*Send the new Index data - 8 bit*/
  SPI_I2S_SendData(SPI1, INDEX_DATA2);
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
  {
  }
  
  
  /*Send the Command - 16 bit*/
  SPI_I2S_SendData(SPI1, reg_value_MSB);
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
  {
  }
  
  SPI_I2S_SendData(SPI1, reg_value_LSB);
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
  {
  }
  
  /*Delay required for proper Chip Select Timing*/
  Delay(1); 
  
  /*High the Chip Select*/
  SPI_TFT_CS_HIGH();
  
}

/**
* @brief  LCD_CtrlLinesConfig.
*         Configures LCD control lines in Output Push-Pull mode.
* @param  None
* @retval None
*/
void LCD_CtrlLinesConfig(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Enable FSMC, GPIOD, GPIOE, AFIO clocks */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
                         RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF | 
                         RCC_APB2Periph_GPIOG | RCC_APB2Periph_GPIOA | 
                         RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
  
  /* Configure PD.00(D2), PD.01(D3), PD.04(NOE), PD.05(NWE), PD.08(D13), PD.09(D14),
  PD.10(D15), PD.14(D0), PD.15(D1) as Alternate function Push-Pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
                                GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_14 | 
                                GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
  
  /* Configure PE.07(D4), PE.08(D5), PE.09(D6), PE.10(D7), PE.11(D8), PE.12(D9), PE.13(D10),
  PE.14(D11), PE.15(D12) as Alternate function push-Pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | 
                                GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | 
                                GPIO_Pin_15;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
  
  
  /* Configure PG.12 - LCD-CS */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_Init(GPIOG, &GPIO_InitStructure);
  
  
  /* Configure PC1, LCD_Reset */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  
}

/**
* @brief  LCD_SPIConfig.       
*         Initializes SPI for LCD rgister configuration mode.
* @param  None
* @retval None
*/
void LCD_SPIConfig(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Enable SPI1 and GPIOA clocks */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA \
                         | RCC_APB2Periph_GPIOG, ENABLE);
  
  /* Configure SPI1 pins: NSS, SCK, MISO and MOSI */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  /* RS is controlled by software */
  /* Configure PA4(SPI-EN) as Output Push-Pull mode.*/
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  
  /* Deselect the TFT: Chip Select high */
   SPI_TFT_CS_HIGH();
  
  /* SPI configuration as Master */
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; 
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);
  
  /* Enable SPI */
  SPI_Cmd(SPI1, ENABLE);
  
}


/**
* @brief  LCD_FSMCConfig.
*         Configures the Parallel interface (FSMC) for LCD(Parallel mode)
* @param  None
* @retval None
*/
void LCD_FSMCConfig(void)
{
  FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
  FSMC_NORSRAMTimingInitTypeDef  p;
  
  /*-- FSMC Configuration ----------------------------------------------------*/
  /*----------------------- SRAM Bank 4 --------------------------------------*/
  /* FSMC_Bank1_NORSRAM4 configuration */
  p.FSMC_AddressSetupTime = 0;
  p.FSMC_AddressHoldTime = 0;
  p.FSMC_DataSetupTime =1;
  p.FSMC_BusTurnAroundDuration = 0;
  p.FSMC_CLKDivision = 0;
  p.FSMC_DataLatency = 0;
  p.FSMC_AccessMode = FSMC_AccessMode_A;
  
  /* Color LCD configuration ------------------------------------
  LCD configured as follow:
  - Data/Address MUX = Disable
  - Memory Type = SRAM
  - Data Width = 16bit
  - Write Operation = Enable
  - Extended Mode = Enable
  - Asynchronous Wait = Disable */
  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;
  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
  FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
  
  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  
  
  /* BANK 4 (of NOR/SRAM Bank 1~4) is enabled */
  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);
}

/**
* @brief  CopyStartupImagesToExtSRAM.
*         Copy startup Display images from NOR to SRAM Refresh buffers
*         using DMA
* @param  None
* @retval None 
*/
void CopyStartupImagesToExtSRAM(void)
{

  /* Static images are already present in NOR memory of MB672
  STM3210E- EVAL Evaluation board. Images are copied by the firmware from 
  NOR memory to on-board external SRAM during firmware initialization. 
  Then image files are refreshed on TFT-LCD by microcontroller from external
  SRAM only. These images are by default programmed in NOR memory of MB672
  STM3210E- EVAL Evaluation board. In case, images are not available in 
  NOR memory, they can be easily programmed in NOR memory using DFU.
  Images are available in the package.Images can also directly refreshed by the
  NOR memory memory using ImageSourceAddress = NOR Image source address */
  
 
  /* Write/read to/from FSMC SRAM memory */
  /* Enable the FSMC Clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
 
  /* Configure FSMC Bank1 NOR/SRAM2 */
  NOR_Init();
  
  /* Read NOR memory ID */
  NOR_ReadID(&NOR_ID);
  
  NOR_ReturnToReadMode();
  
  /* Configure FSMC Bank1 NOR/SRAM3 */
  SRAM_Init();
   
  /* Configure DMA interrupt for image handling */
  SRAM_ImageCopyDMAIntConfig();  
  
  /* Copy images from the NOR memory to SRAM*/
  /* First two images on NOR address map are slideshow images ;
     Start from third image for Banner display */
  NOR_ImageIndex = 2;
  
   /* Load first two images in SRAM Buffer for display */
  SRAM_ImageCopyWithDMA(NORImageFileAddrMap[NOR_ImageIndex++],SRAM_IMAGE1_ADDR);  
  while(DMAComplete == FALSE)
  {
  }   
  SRAM_ImageCopyWithDMA(NORImageFileAddrMap[NOR_ImageIndex++],SRAM_IMAGE2_ADDR); 
  while(DMAComplete == FALSE)
  {
  } 
  
}

/**
* @brief  SRAM_ImageCopyDMAIntConfig.
*         Configure DMA interrupts for Copy from SRAM to NOR
* @param  None
* @retval None 
*/
static void SRAM_ImageCopyDMAIntConfig(void)
{
  
  /* Set the Vector Table base address at 0x08000000 */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0000);
  
  /* Configure the Priority Group to 2 bits */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
  
   /* Enable DMA2 channel1 IRQ Channel */
  NVIC_InitStructure.NVIC_IRQChannel =  DMA2_Channel1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);  
  
  /* Enable DMA2 channel1 IRQ Channel */
  NVIC_InitStructure.NVIC_IRQChannel =  DMA2_Channel2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);  
  
  
}  

/**
* @brief  SRAM_ImageCopyWithDMA
*         Configure DMA to Copy itmpa images from SRAM to NOR
* @param  src_address: Image Source Address
*         dest_address: Image Destination Address
* @retval None 
*/
static void SRAM_ImageCopyWithDMA(uint32_t src_address,uint32_t dest_address)
{
  /* Configure clock for DMA2 Controller */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2,ENABLE); 
   
  /* DMA Data transfer flag for SRAM buffer update*/
  DMAComplete = FALSE;
  
  /* Deintialize DMA Channels */
  DMA_DeInit(DMA2_Channel2); 
  DMA_DeInit(DMA2_Channel1);
  
  /* DMA2 channel1 configuration */ 
  DMA2_Channel1->CPAR  = (uint32_t)src_address; 
  DMA2_Channel1->CMAR  = (uint32_t)dest_address;  
  DMA2_Channel1->CNDTR = 40000;
  DMA2_Channel1->CCR |= DMA_DIR_PeripheralSRC| DMA_Mode_Normal |
                        DMA_PeripheralInc_Enable | DMA_MemoryInc_Enable |
                        DMA_PeripheralDataSize_HalfWord | DMA_MemoryDataSize_HalfWord |
                        DMA_Priority_High | DMA_M2M_Enable;
   
  /* Enable DMA2 Channel1 Transfer Complete interrupt */
  DMA2_Channel1->CCR |= DMA_IT_TC;  
   
  /* Enable DMA2 channel1 for start the transfer from NOR to SRAM*/ 
  DMA2_Channel1->CCR |=  ((uint32_t)0x00000001);
 
  /* DMA2 channel2 configuration */ 
  DMA2_Channel2->CPAR  = (uint32_t)(src_address + 0x13881);
  DMA2_Channel2->CMAR  = (uint32_t)(dest_address + 0x13881);
  DMA2_Channel2->CNDTR = 36866;
  DMA2_Channel2->CCR |= DMA_DIR_PeripheralSRC| DMA_Mode_Normal |
                        DMA_PeripheralInc_Enable | DMA_MemoryInc_Enable |
                        DMA_PeripheralDataSize_HalfWord | DMA_MemoryDataSize_HalfWord |
                        DMA_Priority_High | DMA_M2M_Enable; 
  
  /* Enable DMA2 Channel2 Transfer Complete interrupt */
   DMA2_Channel2->CCR |= DMA_IT_TC;  
   /* Enable DMA2 channel2 for compleate data transfer from NOR to SRAM*/ 
   DMA2_Channel2->CCR |=  ((uint32_t)0x00000001);
  
  /* Wait for DMA transfer Complete */
  while(DMAComplete == FALSE)
  {
  } 
}

/**
* @brief  CopyNewImagetoSRAM.
*         Copy new image to the external SRAM from NOR memory
* @param  src_address: Image Source Address
*         dest_address: Image Destination Address
* @retval None 
*/
void CopyNewImageToExtSRAM(uint32_t src_address,uint32_t dest_address)
{
   DMAComplete = FALSE;  
  /* Disable DMA2 Channel1 and Channel2  */
  DMA2_Channel1->CCR &=((uint32_t)0xFFFFFFFE);        
  DMA2_Channel2->CCR &=((uint32_t)0xFFFFFFFE);       
   
   /* DMA2 Channel 1 configuration for new image */
  DMA2_Channel1->CNDTR =  40000;                  /* Load DMA Data Counter */
  DMA2_Channel1->CPAR = (uint32_t)(src_address);  /* Load DMA source address */
  DMA2_Channel1->CMAR = (uint32_t)(dest_address); /* Load DMA Destination address*/
 
  DMA2_Channel1->CCR |= ((uint32_t)0x00000001);    /* Enable DMA Channel */
  
  /* DMA2 Channel 2 configuration for new image */
  DMA2_Channel2->CNDTR = 36866 ;                   /* Load DMA Data Counter */
  /* Load DMA source address */
  DMA2_Channel2->CPAR = (uint32_t)(src_address + 0x13881);
  /* Load DMA Destination address */
  DMA2_Channel2->CMAR = (uint32_t)(dest_address + 0x13881); 

  /* Enable DMA2 channel2 */
  DMA2_Channel2->CCR |= ((uint32_t)0x00000001);     
  
  /* Wait for DMA transfer Complete */
  while(DMAComplete == FALSE)
  {
  }   
  
}  

/**
* @brief   ExternalSRAMCheckBitmapFiles
*          Checks if the bitmap files (slides) are already loaded
*          in the external SRAM.
* @param  None
* @retval status of image file availability
          0: Images are available
          1: Images are not avilable 
*/

uint32_t ExternalSRAMCheckBitmapFiles(void)
{
  
  /* Configure FSMC Bank1 NOR/SRAM3 */
  SRAM_Init();
  
  imageTab[0] = *(vu8 *)(SRAM_IMAGE1_ADDR);
  imageTab[1] = *(vu8 *)(SRAM_IMAGE1_ADDR + 1);
  
  
 if(Buffercmp(imageTab, SlidesCheck, 2)!= 0) return 1;
  
  imageTab[0] = *(vu8 *)((SRAM_IMAGE1_ADDR + (2 * IMAGE_SIZE)));
  imageTab[1] = *(vu8 *)((SRAM_IMAGE1_ADDR + (2 * IMAGE_SIZE)) + 1);
  
  /* Check if images are loaded in SRAM */
  if(Buffercmp(imageTab, SlidesCheck, 2)!= 0) return 1;
  
  return 0;
}

/**
* @brief  Buffercmp.
*         Compares two buffers.
* @param  pBuffer1, pBuffer2: buffers to be compared.
*         BufferLength: buffer's length
* @retval 0: pBuffer1 identical to pBuffer2
*         1: pBuffer1 differs from pBuffer2 
*/
static uint8_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
  while(BufferLength--)
  {
    if(*pBuffer1 != *pBuffer2)
    {
      return 1;
    }
    
    pBuffer1++;
    pBuffer2++;
  }
  
  return 0;
}

/**
* @brief  LCD_DriverConfig
*         LCD driver configuration to display images on LCD
* @param  None
* @retval None
* 
*/
void LCD_DriverConfig(void)
{
  
  /* Synchronisation Signal Configuration */
  LCD_SynchSignalConfig();     
  
  /* Configure Timer 2 to manage Slide Show View */
  SlideShow_TimerConfig();  
  
  /* Configure Timer 2 to manage Slide Show View */
  FrameRate_TimerConfig();
  
  /* Image Start Address */
  ImageSourceAddrCounter = ImageSourceAddress;
  
  /* Configure DMA to transfer data from SRAM to TFT-LCD */
  LCD_DriverDMAConfig();
  
  /* Interrupt configuration for LCD Driver */
  LCD_DriverInterruptConfig();
  
  /* Intialize synchronisation signals for image display start */   
  TFT_VSYNC_LOW;     
  TFT_HSYNC_LOW;
 
  /* Timer 2 Slide show control disable */
  TIM2->CR1 &= (uint16_t)0x03FE;  
  
  /* TIM3 Frame rate control timer enable */ 
  TIM_Cmd(TIM3, ENABLE);
  
  /* Enable first DMA transfer */   
  DMA_Cmd(DMA1_Channel1, ENABLE);       
  
} 

/**
* @brief  LCD_SynchSignalConfig
*         Configuration of TFT-LCD HSYNC and VSYNC synchronisation signals
*         TFT_LCD requires three signals for operation : LCD clock ,Hsync and Vsync
*         LCD clock is given by inverting FSMC WE .
* @param  None
* @retval None
* 
*/
static void LCD_SynchSignalConfig(void)
{
  
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Enabl GPIO clocks */
  RCC_APB2PeriphClockCmd(TFT_VSYNC_GPIO_PORT_CLOCK | TFT_HSYNC_GPIO_PORT_CLOCK, ENABLE);
 
  
  /* Configure PA8 :VSYNC Configuration as Output Push-Pull */
  GPIO_InitStructure.GPIO_Pin =  TFT_VSYNC_GPIO_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
  GPIO_Init(TFT_VSYNC_GPIO_PORT, &GPIO_InitStructure);  
  
  /* Configure PC6 : HSYNC  as Output Push-Pull */
  GPIO_InitStructure.GPIO_Pin =  TFT_HSYNC_GPIO_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
  GPIO_Init(TFT_HSYNC_GPIO_PORT, &GPIO_InitStructure);       

}

/**
* @brief  LCD_DriverDMAConfig
*         DMA channels configuration to send data to FSMC TFT-LCD.
* @param  None
* @retval None
* 
*/
static void LCD_DriverDMAConfig(void)
{
  /* Configure clock for DMA Controller */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
  
  /* Deintialize DMA Channels */
  DMA_DeInit(DMA1_Channel1);   
  DMA_DeInit(DMA1_Channel2);
  DMA_DeInit(DMA1_Channel3);     
   
  /* DMA1 Channel1 Configuration for line front porch */
  DMA1_Channel1->CCR &=((uint32_t)0xFFFFFFFE); 
  DMA1_Channel1->CCR &= ((uint32_t)0xFFFF800F);
  DMA1_Channel1->CCR |= DMA_DIR_PeripheralSRC| DMA_Mode_Normal |
                        DMA_PeripheralInc_Disable | DMA_MemoryInc_Disable |
                        DMA_PeripheralDataSize_HalfWord | DMA_MemoryDataSize_HalfWord |
                        DMA_Priority_High | DMA_M2M_Enable;
  DMA1_Channel1->CNDTR = LCD_LINE_FRONT_PORCH;
  DMA1_Channel1->CPAR  = (uint32_t)DummyDisplayBuffer; 
  DMA1_Channel1->CMAR  = (uint32_t)(LCD_BASE);      
  
  
  /* DMA1 Channel2 Configuration for valid line data */
  DMA1_Channel2->CCR &=((uint32_t)0xFFFFFFFE); 
  DMA1_Channel2->CCR &= ((uint32_t)0xFFFF800F);
  DMA1_Channel2->CCR |= DMA_DIR_PeripheralSRC| DMA_Mode_Normal |
                        DMA_PeripheralInc_Enable | DMA_MemoryInc_Disable |
                        DMA_PeripheralDataSize_HalfWord | DMA_MemoryDataSize_HalfWord |
                        DMA_Priority_High | DMA_M2M_Enable;
  DMA1_Channel2->CNDTR = LCD_HORZ_LINE;
  DMA1_Channel2->CPAR  = (uint32_t)DummyDisplayBuffer; 
  DMA1_Channel2->CMAR  = (uint32_t)(LCD_BASE);      
  
  /*DMA1 Channel3 Configuration for back porch data*/
  DMA1_Channel3->CCR &=((uint32_t)0xFFFFFFFE); 
  DMA1_Channel3->CCR &= ((uint32_t)0xFFFF800F);
  DMA1_Channel3->CCR |= DMA_DIR_PeripheralSRC| DMA_Mode_Normal |
                        DMA_PeripheralInc_Disable | DMA_MemoryInc_Disable |
                        DMA_PeripheralDataSize_HalfWord | DMA_MemoryDataSize_HalfWord |
                        DMA_Priority_High | DMA_M2M_Enable;
  DMA1_Channel3->CNDTR = LCD_LINE_BACK_PORCH;
  DMA1_Channel3->CPAR  = (uint32_t)DummyDisplayBuffer; 
  DMA1_Channel3->CMAR  = (uint32_t)(LCD_BASE);      
  
  /* Enable DMA Channel1 Transfer Complete interrupt */
   DMA1_Channel1->CCR |= DMA_IT_TC;
  /* Enable DMA Channel2 Transfer Complete interrupt */
   DMA1_Channel2->CCR |= DMA_IT_TC;
  /* Enable DMA Channel3 Transfer Complete interrupt */
   DMA1_Channel3->CCR |= DMA_IT_TC;
}

/**
* @brief  LCD_DriverInterruptConfig
*         Configures the used IRQ Channels for TFT-LCD driver
* @param  None
* @retval None
* 
*/
static void LCD_DriverInterruptConfig(void)
{ 

   /* Configure the Priority Group to 2 bits */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); 
  
  /* Enable the DMA1 channel1 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  /* Enable DMA1 channel2 IRQ Channel */
  NVIC_InitStructure.NVIC_IRQChannel =  DMA1_Channel2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  /* Enable DMA1 channel3 IRQ Channel */
  NVIC_InitStructure.NVIC_IRQChannel =  DMA1_Channel3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  /* Enable the Frame Rate Control, TIM3 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  NVIC_Init(&NVIC_InitStructure);
  
  /* Enable the SlideShow , TIM2 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  NVIC_Init(&NVIC_InitStructure);
  
  /* Clear TIM2 update  interrupt pending bit */
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  
  /* Clear TIM3 update interrupt pending bit  */
  TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
  
}

/**
* @brief  FrameRate_TimerConfig.
*         Timer configuration for frame rate control for image display
* @param  None
* @retval None 
*/
static void FrameRate_TimerConfig(void)
{
  uint16_t frameRatePrescalor = 0;
  
  /* TIM2 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);     
  
  /* Time base configuration */
   /* Time base configuration */
   /* TIM3_CLK = (PCLK1)/4 = 18MHz. If (APB1 prescaler =1) x1,else x2.
     TIM3_CLK = 800 Hz*/   
  
  /* Frame Rate is in Hertz, 
  Accordingly Timer Prescalor is configured*/
  frameRatePrescalor = ((800/FRAME_RATE)-1);  

  TIM_DeInit(TIM3);
  TIM_TimeBaseStructure.TIM_Period = FRAME_TIM_PERIOD;
  TIM_TimeBaseStructure.TIM_Prescaler = frameRatePrescalor;
  TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    
  /* TIM Update IT enable */
  TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
  
}  

/**
* @brief  SlideShow_TimerConfig.
*         Timer configuration for Slideshow interval control for image change
* @param  None
* @retval None 
*/
static void SlideShow_TimerConfig(void)
{
  uint16_t slideShowPrescalor = 0;
  
  /* TIM2 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);    
  
  /* Time base configuration */
  /* TIM2_CLK = ((PCLK1)/4)*2 = 36MHz. If (APB1 prescaler =1) x1,else x2.
    TIM2_CLK = 800 Hz*/  
  
  /* SLIDESHOW_TIME_GAP is in seconds 
  Accordingly Timer Prescalor is configured*/
  slideShowPrescalor = ((800* SLIDESHOW_TIME_GAP)-1);  
  
  TIM_DeInit(TIM2);
  TIM_TimeBaseStructure.TIM_Period = SLIDESHOW_TIM_PERIOD;
  TIM_TimeBaseStructure.TIM_Prescaler = slideShowPrescalor;
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  /* TIM Update IT enable */
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
  
} 


/**
* @}
*/ 

/**
* @}
*/ 

/**
* @}
*/



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

