
/**
 ******************************************************************************
 *
 * @file        MG32x02z_SPILCD_API.c
 * @brief       The code is Using SPI of MG32x02z to control ILI9341 
 *
 * @par         Project
 *              MG32x02z
 * @version     V1.00
 * @date        2022/12/23
 * @author      Megawin Software Center
 * @copyright   Copyright (c) 2017 MegaWin Technology Co., Ltd.
 *              All rights reserved.
 * 
 ******************************************************************************* 
 * @par Disclaimer
 * The Demo software is provided "AS IS" without any warranty, either
 * expressed or implied, including, but not limited to, the implied warranties
 * of merchantability and fitness for a particular purpose. The author will
 * not be liable for any special, incidental, consequential or indirect
 * damages due to loss of data or any other reason.
 * These statements agree with the world wide and local dictated laws about
 * authorship and violence against these laws.
 *******************************************************************************
 *******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "MG32x02z_Common.h"
#include "MG32x02z_SPILCD_API.h"
#include "MG32x02z_SPILCDFont.h"


/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define LCD_SPI         URT0


/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
Display_HandleTypeDef   LCD_CTR;


/* Private function prototypes -----------------------------------------------*/
void BSP_LCD_IRQHandler(void);

static void BSP_LCD_Reset(uint32_t LCDRst_Time);
static void BSP_LCD_SelectRegister(uint16_t Register);
static void BSP_LCD_WriteData(uint16_t Data);
static void BSP_LCD_WriteData8(uint8_t Data);
static uint16_t BSP_LCD_ReadData(void);
static void BSP_LCD_WriteRegister(uint16_t Register, uint16_t Value);
static void BSP_LCDPowerOn_Init(void);
static void BSP_LCD_BackLight(uint16_t Duty);
static void BSP_LCD_Scan_Dir(uint8_t dir);
static void BSP_LCD_Display_Dir(uint8_t dir);
static void BSP_LCD_SetCursor(uint16_t Xpos, uint16_t Ypos);
static void BSP_LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t color);
  
/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/


/**
 *******************************************************************************
 * @brief	   Show char in the LCD. 
 * @details    
 * @param[in]  Char_X: Show X coordinate.
 * @param[in]  Char_Y: Show Y coordinate.
 * @param[in]  num: Char ASCII code.
 * @param[in]  Char_Color: Char color.
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
void BSP_LCD_ShowChar(uint16_t Char_X, uint16_t Char_Y, uint8_t num, uint16_t Char_Color)
{
    uint8_t  temp,t1,t;
    uint16_t y0 = Char_Y;
    uint8_t  csize = (LCD_STRING_SIZE / 8 ) * (LCD_STRING_SIZE / 2); 
    
    num = num - ' ' ;
    for(t = 0; t < csize; t++)
    {   
        temp = asc2_1608[num][t];         
        
        for(t1=0;t1<8;t1++)
        {
            if(temp & 0x80)
            {
                BSP_LCD_DrawPoint(Char_X, Char_Y, Char_Color);
            }

            temp <<= 1;
            Char_Y++;
            if(Char_X >= LCD_CTR.Width)
            {
                return;
            }                
            if((Char_Y - y0) == LCD_STRING_SIZE)
            {
                Char_Y = y0;
                Char_X++;
                if(Char_X >= LCD_CTR.Width)return;            
                break;
            }
        }
    }
}

/**
 *******************************************************************************
 * @brief     Show string in the LCD.
 * @details    
 * @param[in] x: The LCD shows starting point X coordinate.
 * @param[in] y: The LCD shows starting point Y coordinate.
 * @param[in] width  : The string display range width in the LCD.
 * @param[in] height : The string display range height in the LCD.
 * @param[in] StringColor: String color.
 * @param[in] pString: String data pointer.
 * @return      
 * @exception 
 * @note       
 *******************************************************************************
 */
void BSP_LCD_ShowString(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t StringColor, char *pString)
{
    uint16_t x0;              
    
    x0      = x;
    width  += x;       // Get range ending point X coordinate.
    height += y;       // Get range ending point Y coordinate.
    
    /*Specified range over LCD show range.*/
    if( width > LCD_CTR.Width || height > LCD_CTR.Height)
    {
        return;
    }
    /*Start showing*/
    while((*pString <= '~')&&(*pString >= ' '))
    {
        /*Detect X coordinate wheter exceed or not.*/
        if(x >= width)
        {
            x = x0;                                   // X coordinate return to default X coordinate.
            y += LCD_STRING_SIZE;                     // Increase showing Y coordinate.
        }
        /*Detect Y coordinate wheter exceed or not.*/
        if(y >= height)
        {
            break;                                    // End showing string.
        }
        BSP_LCD_ShowChar(x, y, *pString, StringColor);
        x += LCD_STRING_SIZE / 2;
        pString++;
    }
}

/**
 *******************************************************************************
 * @brief     LCD fill single color in the specific area.	    
 * @details    
 * @param[in] Fill_sX: Start X coordinate.
 * @param[in] Fill_sY: Start Y coordinate.
 * @param[in] Fill_eX: End X coordinate.
 * @param[in] Fill_eY: End Y coordinate.
 * @param[in] Fill_color: Fill color.
 * @return       
 * @exception    
 * @note   
 *******************************************************************************
 */
void BSP_LCD_FillMonochrome(uint16_t Fill_sX, uint16_t Fill_sY, uint16_t Fill_eX, uint16_t Fill_eY, uint16_t Fill_color)
{
    uint32_t LCD_FSC_XAxis;
    uint32_t LCD_FSC_YAxis;
    uint32_t LCD_FSC_Len;
    
    LCD_FSC_Len = Fill_eX - Fill_sX + 1;
    
    for( LCD_FSC_YAxis = Fill_sY; LCD_FSC_YAxis < (Fill_eY + 1); LCD_FSC_YAxis++)
    {
        BSP_LCD_SetCursor(Fill_sX, (uint16_t)LCD_FSC_YAxis);                
        LCD_CTR.SelectReg(LCD_CTR.GRAMcmd);           
        for(LCD_FSC_XAxis= 0; LCD_FSC_XAxis < LCD_FSC_Len; LCD_FSC_XAxis++)
        {
            LCD_CTR.WriteData(Fill_color);
        }            
    }
}

/**
 *******************************************************************************
 * @brief	  LCD initial.
 * @details     
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
void API_LCD_Init(void)
{
    URT_BRG_TypeDef     LCD_BRG;
    DMA_BaseInitTypeDef LCD_DMA_Init;
    
    /*Parameter Initial*/
    LCD_CTR.Reset         = BSP_LCD_Reset;
    LCD_CTR.BackLight     = BSP_LCD_BackLight;
    LCD_CTR.SelectReg     = BSP_LCD_SelectRegister;
    LCD_CTR.WriteData     = BSP_LCD_WriteData;
    LCD_CTR.WriteData8    = BSP_LCD_WriteData8;
    LCD_CTR.ReadData      = BSP_LCD_ReadData;
    LCD_CTR.WriteRegister = BSP_LCD_WriteRegister;
    LCD_CTR.PointColor    = WHITE;
    LCD_CTR.BackColor     = BLACK;
    LCD_CTR.ID            = 0x9341;
    
    /*GPIO Initial*/
    LCD_CTR.BackLight(0x0000);       // Backlight OFF.
    
    API_GPIO_PinConfig( LCD_RSTN_IOM , Data_DIR_OUT_PP, 0);
    API_GPIO_PinConfig( LCD_RS_IOM   , Data_DIR_OUT_PP, 0);
    API_GPIO_PinConfig( LCD_CS_IOM   , Data_DIR_OUT_PP, 0);
    API_GPIO_PinConfig( LCD_SCK_IOM  , Data_DIR_OUT_PP, LCD_SCK_AFS);
    API_GPIO_PinConfig( LCD_SDI_IOM  , Data_DIR_OUT_PP, LCD_SDI_AFS);
    API_GPIO_PinConfig( LCD_SDO_IOM  , Data_DIR_IN_RU , LCD_SDO_AFS);
    API_GPIO_PinConfig( LCD_BL_IOM   , Data_DIR_OUT_PP, 0);
    
    /*SPI Initial ( URT Module )*/
    //Baud-Rate
    LCD_BRG.URT_InternalClockSource = URT_BDClock_PROC;
    LCD_BRG.URT_BaudRateMode = URT_BDMode_Combined;
    LCD_BRG.URT_PrescalerCounterReload = 0;	                  // Set PSR
    LCD_BRG.URT_BaudRateCounterReload  = 0;	                  // Set RLR
    URT_BaudRateGenerator_Config(LCD_SPI, &LCD_BRG);		  // BR115200 = f(CK_URTx)/(PSR+1)/(RLR+1)/(OS_NUM+1)
    URT_BaudRateGenerator_Cmd(LCD_SPI, ENABLE);	              // Enable BaudRateGenerator
                                                                 
    URT_TXClockSource_Select(LCD_SPI, URT_TXClock_Internal);  // URT_TX use BaudRateGenerator
    URT_RXClockSource_Select(LCD_SPI, URT_RXClock_Internal);  // URT_RX use BaudRateGenerator
    URT_TXOverSamplingSampleNumber_Select(LCD_SPI, 4);	      // Set TX OS_NUM
    URT_RXOverSamplingSampleNumber_Select(LCD_SPI, 4);	      // Set RX OS_NUM
    URT_RXOverSamplingMode_Select(LCD_SPI, URT_RXSMP_3TIME);     
    URT_TX_Cmd(LCD_SPI, ENABLE);	                          // Enable TX
    URT_RX_Cmd(LCD_SPI, ENABLE);	                          // Enable RX
    
    //Character format
    // - Data bit     : 8 bit
    // - Dart order   : MSB
    // - Parity bit   : No
    // - Stop bit     : 1 bit
    // - Data inverse : No
    LCD_SPI->CR1.B[2] = (((uint8_t)URT_DataLength_8)  | 
                         ((uint8_t)URT_DataTyped_MSB) | 
                         ((uint8_t)URT_Parity_No)     | 
                         ((uint8_t)URT_StopBits_1_0));
    
    LCD_SPI->CR1.B[0] = (((uint8_t)URT_DataLength_8)  | 
                         ((uint8_t)URT_DataTyped_MSB) | 
                         ((uint8_t)URT_Parity_No)     | 
                         ((uint8_t)URT_StopBits_1_0));
    
    //RX / TX Data bit no inverse.
    LCD_SPI->CR4.B[0] = (LCD_SPI->CR4.B[0] & (~(URT_CR4_RDAT_INV_mask_b0|URT_CR4_TDAT_INV_mask_b0)));
 
    //URT mode is SYNC mode.
    URT_Mode_Select(LCD_SPI, URT_SYNC_mode);
    //URT data line is 2 line.
    URT_DataLine_Select(LCD_SPI, URT_DataLine_2);
    //{CPOL , CPHA} = { 0 , 0}
    URT_CPHAMode_Select(LCD_SPI , URT_CPHA0_LeadEdge);
    URT_CPOLMode_Select(LCD_SPI , URT_CPOL0_Low );
    //SPI master (MOSI) IDLE status : Last byte status)
    URT_SPIMasterDataOutputIdleStatus_Select(LCD_SPI,URT_mSPI_MOSI_Idle_LastBit);
    
    // CLK function enable.
    URT_CLKSignal_Cmd(LCD_SPI,ENABLE);
    // Enable URT function.
    URT_Cmd(LCD_SPI, ENABLE);
    
    /*DMA Init (for LCD background update)*/
    DMA_Cmd( ENABLE);
    DMA_BaseInitStructure_Init(&LCD_DMA_Init);
    
    /*LCD Power On Initial*/
    LCD_CTR.Reset(5);
    Delay(120);

    BSP_LCDPowerOn_Init();
    BSP_LCD_Display_Dir(0);
    BSP_LCD_Clear(BLACK);
    
    BSP_LCD_InitCallback();
    
    LCD_CTR.BackLight(0xFFFF);
    

}

/**
 *******************************************************************************
 * @brief	   The whole LCD shows the single color.  
 * @details
 * @param[in]  color : Show the color.
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
void BSP_LCD_Clear(uint16_t color)
{
    __IO uint32_t index=0;
    __IO uint32_t totalpoint;

    totalpoint = LCD_CTR.Width;
    totalpoint *= LCD_CTR.Height;                        
    if((LCD_CTR.ID == 0X6804)&&(LCD_CTR.Direct != 0))     
    {
        LCD_CTR.Direct  = 0;
        LCD_CTR.SetXcmd = 0X2A;
        LCD_CTR.SetYcmd = 0X2B;
        BSP_LCD_SetCursor(0x00,0x0000);               
        LCD_CTR.Direct  = 1;
        LCD_CTR.SetXcmd = 0X2B;
        LCD_CTR.SetYcmd = 0X2A;
    }else BSP_LCD_SetCursor(0x00,0x0000);             
    LCD_CTR.SelectReg(LCD_CTR.GRAMcmd);                 

    for(index = 0; index < totalpoint; index++)
    {
        LCD_CTR.WriteData(color);
    }
}

/**
 *******************************************************************************
 * @brief	  LCD initial complete callback function.
 * @details     
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
__WEAK void BSP_LCD_InitCallback(void)
{
    //=========================================================
    //NOTE : This function should not be modifyed, when the 
    //       callback is needed, the MID_URT_RxCpltCallback 
    //       can be implemented in the user file.
}

/**
 *******************************************************************************
 * @brief	   LCD module Reset 
 * @details     
 * @param[in]  LCDRst_Time : LCD reset signal time.
 * @return      
 * @exception  No 
 * @note       Use the function must initial systick by middleware.
 *******************************************************************************
 */
static void BSP_LCD_Reset(uint32_t LCDRst_Time)
{
    __SPI_LCD_RESET_ENABLE();
    Delay(LCDRst_Time);
    __SPI_LCD_RESET_DISABLE();
}

/**
 *******************************************************************************
 * @brief	   Select control LCD register 
 * @details    
 * @param[in]  Register
 * @return      
 * @exception  No 
 * @note        
 *******************************************************************************
 */
static void BSP_LCD_SelectRegister(uint16_t Register)
{
    __LCD_RS_CLR();
    __LCD_CS_CLR();                                 //LCD_CS=0
    
    LCD_SPI->TDAT.B[0] = (uint8_t)Register;
    while((LCD_SPI->STA.W & LCD_SPI_TCF) == 0);
    
    __LCD_CS_SET();                                //LCD_CS=1
}

/**
 *******************************************************************************
 * @brief	  Output 16 bit data to LCD module.  
 * @details  
 * @param[in] Data : 16 bit output data.
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
static void BSP_LCD_WriteData(uint16_t Data)
{
    __LCD_RS_SET();
    __LCD_CS_CLR();                                           //LCD_CS=0
    
    LCD_SPI->TDAT.B[0] = (uint8_t)(Data >> 8);
    while((LCD_SPI->STA.W & LCD_SPI_TXF) == 0);
    
    LCD_SPI->TDAT.B[0] = (uint8_t)Data;
    while((LCD_SPI->STA.W & LCD_SPI_TCF) == 0);

    __LCD_CS_SET();                                           //LCD_CS=1
}

/**
 *******************************************************************************
 * @brief	  Output 8 bit data to LCD module.   
 * @details     
 * @param[in] Data : 8 bit output data.
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
static void BSP_LCD_WriteData8(uint8_t Data)   
{
    __LCD_RS_SET();
    __LCD_CS_CLR();  
    
    LCD_SPI->TDAT.B[0] = Data;
    while((LCD_SPI->STA.W & LCD_SPI_TCF) == 0);

    __LCD_CS_SET();  
}

/**
 *******************************************************************************
 * @brief	   Read 16-bti data from LCD module. 
 * @details     
 * @return      
 * @exception  No 
 * @note        
 *******************************************************************************
 */
static uint16_t BSP_LCD_ReadData(void)
{
    __LCD_RS_SET();
    __LCD_CS_CLR();  
    
    LCD_SPI->TDAT.B[0] = (uint8_t)(0xFF >> 8);
    while((LCD_SPI->STA.W & LCD_SPI_TXF) == 0);
    
    LCD_SPI->TDAT.B[0] = (uint8_t)0xFF;
    while((LCD_SPI->STA.B[0] & LCD_SPI_TCF) == 0);

    __LCD_CS_SET();  //LCD_CS=1
    return 0;
}

/**
 *******************************************************************************
 * @brief	   Write LCD register 
 * @details   
 * @param[in]  Register: which register.
 * @param[in]  Vaule : Write register value.
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
static void BSP_LCD_WriteRegister(uint16_t Register, uint16_t Value)
{
    __LCD_RS_SET();
    __LCD_CS_CLR();  
    
    LCD_SPI->TDAT.B[0] = (uint8_t)Register;
    while((LCD_SPI->STA.W & LCD_SPI_TCF) == 0);
    __LCD_CS_SET();  

    __LCD_RS_SET();
    
    __LCD_CS_CLR();  
    LCD_SPI->TDAT.B[0] = (uint8_t)Value;
    while((LCD_SPI->STA.W & LCD_SPI_TCF) == 0);
    __LCD_CS_SET();  
}

/**
 *******************************************************************************
 * @brief	  LCD power on initial.
 * @details     
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
static void BSP_LCDPowerOn_Init(void)
{
    /*Software reset*/
    LCD_CTR.SelectReg(0x01);
    Delay(6);
    
    /*Power control A*/
    LCD_CTR.SelectReg(0xCB);
    LCD_CTR.WriteData8(0x39);      // static value 0x39
    LCD_CTR.WriteData8(0x2C);      // static value 0x2C
    LCD_CTR.WriteData8(0x00);      // static value 0x00
    LCD_CTR.WriteData8(0x34);      // Vcore = 1.6V (Default value)
    LCD_CTR.WriteData8(0x02);      // DDVDH = 5.6V (Default value)
    
    /*Power control B*/
    LCD_CTR.SelectReg(0xCF);
    LCD_CTR.WriteData8(0x00);      // static value 0x00
    LCD_CTR.WriteData8(0x55);       
    LCD_CTR.WriteData8(0X30);      // Enable ESD protectoin.

    /*Driver timing control A*/    
    LCD_CTR.SelectReg(0xE8);      
    LCD_CTR.WriteData8(0x85);      //Gate driver overlap timing control = + 1 unit 
    LCD_CTR.WriteData8(0x10);      //EQ timing control : EQ timing, CR timing control : 1 unit.
    LCD_CTR.WriteData8(0x7A);      //Pre-charge timing control : default pre-charge timing.
    
    /*Driver timing control B*/    
    LCD_CTR.SelectReg(0xEA);
    LCD_CTR.WriteData8(0x00);      // Gate driver timing control :
                                   //     1. VG_SW_T1 (EQ to GNE   )= 0 unit.
                                   //     2. VG_SW_T2 (EQ to DDVDH )= 0 unit.
                                   //     3. VG_SW_T3 (EQ to DDVDH )= 0 unit.
                                   //     4. VG_SW_T4 (EQ to GND   )= 0 unit.                                   
    LCD_CTR.WriteData8(0x00);      // static value 0x00
    
    /*Power on sequence control*/
    LCD_CTR.SelectReg(0xED);
    LCD_CTR.WriteData8(0x64);      //CP1 soft start keep 1 frame, CP23 soft start keep 3 frame.
    LCD_CTR.WriteData8(0x03);      //Power on sequence control : En_vcl = VCL 1st frame enable, En_ddvdh = DDVDH 4th frame enable.
    LCD_CTR.WriteData8(0X12);      //Power on sequence control : En_vgh = VGH 2nd frame enable, En_vgl   = VGL 3rd frame enable.
    LCD_CTR.WriteData8(0X81);      //DDVDH enhance mode enable.
                                   
    /*Pump ratio control*/
    LCD_CTR.SelectReg(0xF7);
    LCD_CTR.WriteData8(0x20);      // DDVDH = 2 x VCI (Default value)

    /*Power Control 1*/
    LCD_CTR.SelectReg(0xC0);       
    LCD_CTR.WriteData8(0x1B);      // GVDD = 4.2V 
                                   // GVDD is a reference level for the VCOM level and the grayscale voltage level.

    /*Power Control 2*/            
    LCD_CTR.SelectReg(0xC1);       
    LCD_CTR.WriteData8(0x01);      // DDVDH = VCI X 2, VGH = VCI X 7, VGL = -VCI X 3 

    /*VCOM Control 1*/
    LCD_CTR.SelectReg(0xC5);       
    LCD_CTR.WriteData8(0x30);      // VMH[6:0] = 0x30 (VCOMH = 3.900V)  
    LCD_CTR.WriteData8(0x30);      // VML[6:0] = 0x30 (VMLVCOML = -1.300V)

    /*VCOM Control 2*/
    LCD_CTR.SelectReg(0xC7);       
    LCD_CTR.WriteData8(0XB7);      // VCOMH = VMH - 9 , VCOML = VML - 9

    /*Memory Access Control*/
    LCD_CTR.SelectReg(0x36);       
    LCD_CTR.WriteData8(0x48);      

    /*Pixel Format Set*/
    LCD_CTR.SelectReg(0x3A);
    LCD_CTR.WriteData8(0x55);      // RGB Interface Format = 16 bits / pixel , MCU Interface Format = 16 bits / pixel. 

    /*Frame Rate Control*/
    LCD_CTR.SelectReg(0xB1);
    LCD_CTR.WriteData8(0x00);      // Division ratio is fosc
    LCD_CTR.WriteData8(0x1A);      // Frame Rate = 73Hz 

    /*Display Function Control*/   
    LCD_CTR.SelectReg(0xB6);       
    LCD_CTR.WriteData8(0x0A);      // Gate outputs in non-display are = Interval scan.
                                   // Source outputs in non-display area = {Positive polarity = AGND , Negative polarity = AGND}.
                                   // VCOM output on non-display area = {Positive polarity = AGND , Negative polarity = AGND}.
    LCD_CTR.WriteData8(0xE2);      // The liquid crystal type is normally = Normally white.
                                   // The shift direction of outputs from the source = S720 --> S1.
                                   // Specify the scan cycle interval of gate driver in non-display area : 5 frames.
                                   // Direction of scan reverse.
    LCD_CTR.WriteData8(0x27);      // LCD Driver Line = 320 lines.
    
    /*Enable 3 gamma*/
    LCD_CTR.SelectReg(0xF2);       
    LCD_CTR.WriteData8(0x00);      // Disable 3 gamma control.

    /*Gamma Set*/
    LCD_CTR.SelectReg(0x26);       
    LCD_CTR.WriteData8(0x01);

    /*Positive Gamma Correction*/
    LCD_CTR.SelectReg(0xE0);       
    LCD_CTR.WriteData8(0x0F);
    LCD_CTR.WriteData8(0x2A);
    LCD_CTR.WriteData8(0x28);
    LCD_CTR.WriteData8(0x08);
    LCD_CTR.WriteData8(0x0E);
    LCD_CTR.WriteData8(0x08);
    LCD_CTR.WriteData8(0x54);
    LCD_CTR.WriteData8(0XA9);
    LCD_CTR.WriteData8(0x43);
    LCD_CTR.WriteData8(0x0A);
    LCD_CTR.WriteData8(0x0F);
    LCD_CTR.WriteData8(0x00);
    LCD_CTR.WriteData8(0x00);
    LCD_CTR.WriteData8(0x00);
    LCD_CTR.WriteData8(0x00);

    /*Negative Gamma Correction*/
    LCD_CTR.SelectReg(0XE1);        
    LCD_CTR.WriteData8(0x00);
    LCD_CTR.WriteData8(0x15);
    LCD_CTR.WriteData8(0x17);
    LCD_CTR.WriteData8(0x07);
    LCD_CTR.WriteData8(0x11);
    LCD_CTR.WriteData8(0x06);
    LCD_CTR.WriteData8(0x2B);
    LCD_CTR.WriteData8(0x56);
    LCD_CTR.WriteData8(0x3C);
    LCD_CTR.WriteData8(0x05);
    LCD_CTR.WriteData8(0x10);
    LCD_CTR.WriteData8(0x0F);
    LCD_CTR.WriteData8(0x3F);
    LCD_CTR.WriteData8(0x3F);
    LCD_CTR.WriteData8(0x0F);

    /*Page Address Set*/
    LCD_CTR.SelectReg(0x2B);
    LCD_CTR.WriteData8(0x00);
    LCD_CTR.WriteData8(0x00);
    LCD_CTR.WriteData8(0x01);
    LCD_CTR.WriteData8(0x3f);

    /*Column Address Set*/
    LCD_CTR.SelectReg(0x2A);
    LCD_CTR.WriteData8(0x00);
    LCD_CTR.WriteData8(0x00);
    LCD_CTR.WriteData8(0x00);
    LCD_CTR.WriteData8(0xef);

    /*Sleep OUT*/
    LCD_CTR.SelectReg(0x11);        
    Delay(120);
    /*Display ON*/
    LCD_CTR.SelectReg(0x29);        
}

/**
 *******************************************************************************
 * @brief	  LCD backlight control  
 * @details
 * @param[in] Dyte:
 *   @arg\b   0x0000 : Disable LCD backlight 
 *   @arg\b   0xFFFF : Enable LCD backlight.
 * @return      
 * @exception No  
 * @note        
 *******************************************************************************
 */
static void BSP_LCD_BackLight(uint16_t Duty)
{
    if(Duty == 0x0000)
        __SPI_LCD_BACKLIGHT_OFF();

    if(Duty == 0xFFFF)
        __SPI_LCD_BACKLIGHT_ON();
}

/**
 *******************************************************************************
 * @brief	  Set LCD scan direct  
 * @details   memory write/read direction
 * @param[in] dir: Display Data Direction
 *	@arg\b    L2R_U2D: Normal
 *  @arg\b    L2R_D2U: Y-Mirror
 *  @arg\b    R2L_U2D: X-Mirror
 *  @arg\b    R2L_D2U: X-Mirror Y-Mirror
 *  @arg\b    U2D_L2R: X-Y Exchange
 *  @arg\b    U2D_R2L: XY Exchange X-Mirror
 *  @arg\b    D2U_L2R: X-Y Exchange Y-Mirror
 *  @arg\b    D2U_R2L: XY Exchange XY-Mirror
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
static void BSP_LCD_Scan_Dir(uint8_t dir)
{
    uint16_t regval=0;
    uint16_t dirreg=0;
    uint16_t temp;  
    
    if(LCD_CTR.Direct == 1)
    {
        switch(dir)
        {
            case 0: dir = 6;break;
            case 1: dir = 7;break;
            case 2: dir = 4;break;
            case 3: dir = 5;break;
            case 4: dir = 1;break;
            case 5: dir = 0;break;
            case 6: dir = 3;break;
            case 7: dir = 2;break;
        }
    }
    switch(dir)
    {
        case L2R_U2D:
            regval|=(0<<7)|(0<<6)|(0<<5);
            break;
        case L2R_D2U:
            regval|=(1<<7)|(0<<6)|(0<<5);
            break;
        case R2L_U2D:
            regval|=(0<<7)|(1<<6)|(0<<5);
            break;
        case R2L_D2U:
            regval|=(1<<7)|(1<<6)|(0<<5);
            break;
        case U2D_L2R:
            regval|=(0<<7)|(0<<6)|(1<<5);
            break;
        case U2D_R2L:
            regval|=(0<<7)|(1<<6)|(1<<5);
            break;
        case D2U_L2R:
            regval|=(1<<7)|(0<<6)|(1<<5);
            break;
        case D2U_R2L:
            regval|=(1<<7)|(1<<6)|(1<<5);
            break;
    }

    if(LCD_CTR.ID == 0X5510) dirreg = 0X3600;
    else dirreg = 0x36;

    if((LCD_CTR.ID != 0X5310) && (LCD_CTR.ID != 0X5510))regval |= 0X08;

    if(LCD_CTR.ID == 0X6804)regval |= 0x02;

    LCD_CTR.WriteRegister(dirreg, regval);

    if(regval & 0X20)
    {
        if(LCD_CTR.Width < LCD_CTR.Height)
        {
            temp = LCD_CTR.Width;
            LCD_CTR.Width  = LCD_CTR.Height;
            LCD_CTR.Height = temp;
        }
    }else
    {
        if(LCD_CTR.Width > LCD_CTR.Height)
        {
            temp = LCD_CTR.Width;
            LCD_CTR.Width = LCD_CTR.Height;
            LCD_CTR.Height = temp;
        }
    }

    LCD_CTR.SelectReg(LCD_CTR.SetXcmd);
    if(LCD_CTR.ID == 0X5510)
    {
        LCD_CTR.WriteData(0);
        LCD_CTR.SelectReg(LCD_CTR.SetXcmd + 1);
        LCD_CTR.WriteData(0);
        LCD_CTR.SelectReg(LCD_CTR.SetXcmd + 2);
        LCD_CTR.WriteData((LCD_CTR.Width - 1) >> 8);
        LCD_CTR.SelectReg(LCD_CTR.SetXcmd + 3);
        LCD_CTR.WriteData((LCD_CTR.Width - 1) & 0XFF);
        LCD_CTR.SelectReg(LCD_CTR.SetYcmd);
        LCD_CTR.WriteData(0);
        LCD_CTR.SelectReg(LCD_CTR.SetYcmd + 1);
        LCD_CTR.WriteData(0);
        LCD_CTR.SelectReg(LCD_CTR.SetYcmd + 2);
        LCD_CTR.WriteData((LCD_CTR.Height-1)>>8);
        LCD_CTR.SelectReg(LCD_CTR.SetYcmd + 3);
        LCD_CTR.WriteData((LCD_CTR.Height-1)&0XFF);
    }else
    {
        LCD_CTR.WriteData8(0);
        LCD_CTR.WriteData8(0);
        LCD_CTR.WriteData8((LCD_CTR.Width-1)>>8);
        LCD_CTR.WriteData8((LCD_CTR.Width-1)&0XFF);

        LCD_CTR.SelectReg(LCD_CTR.SetYcmd);
        LCD_CTR.WriteData8(0);
        LCD_CTR.WriteData8(0);
        LCD_CTR.WriteData8((LCD_CTR.Height-1)>>8);
        LCD_CTR.WriteData8((LCD_CTR.Height-1)&0XFF);
    }
}

/**
 *******************************************************************************
 * @brief	  LCD show is Vertical or Horizontal.  
 * @details   
 * @param[in] dir: 0(Vertical {W,H} = {240,320}, Horizontal {W,H} = {320,240} 
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
static void BSP_LCD_Display_Dir(uint8_t dir)
{
    if(dir == 0)                    
    {
        LCD_CTR.Direct  = 0;       
        LCD_CTR.Width   = 240;
        LCD_CTR.Height  = 320;
    }
    else                           
    {
        LCD_CTR.Direct  = 1;       
        LCD_CTR.Width   = 320;
        LCD_CTR.Height  = 240;

    }
    LCD_CTR.GRAMcmd = 0x2C;
    LCD_CTR.SetXcmd = 0x2A;
    LCD_CTR.SetYcmd = 0x2B;
    BSP_LCD_Scan_Dir(DFT_SCAN_DIR);  
}

/**
 *******************************************************************************
 * @brief	   Set LCD cursor. 
 * @details    
 * @param[in]  Xpos: Cursor X coordinate.
 * @param[in]  Ypos: Cursor Y coordinate.
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
static void BSP_LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
{
    LCD_CTR.SelectReg(LCD_CTR.SetXcmd);
    LCD_CTR.WriteData8(Xpos>>8);
    LCD_CTR.WriteData8(Xpos&0XFF);
    
    LCD_CTR.SelectReg(LCD_CTR.SetYcmd);
    LCD_CTR.WriteData8(Ypos>>8);
    LCD_CTR.WriteData8(Ypos&0XFF);
}

/**
 *******************************************************************************
 * @brief	   Draw the color point in X , Y
 * @details     
 * @param[in]  DrawPoint_X: The point X coordinate.
 * @param[in]  DrawPoint_Y: The point Y coordinate. 
 * @param[in]  DrawPoint_color: The point color.
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
static void BSP_LCD_DrawPoint(uint16_t DrawPoint_X, uint16_t DrawPoint_Y, uint16_t DrawPoint_color)
{
    if((DrawPoint_Y >= LCD_CTR.Height) || (DrawPoint_X >= LCD_CTR.Width))
        return;

    LCD_CTR.SelectReg(LCD_CTR.SetXcmd);
    LCD_CTR.WriteData8(DrawPoint_X >> 8);
    LCD_CTR.WriteData8(DrawPoint_X & 0XFF);
    LCD_CTR.SelectReg(LCD_CTR.SetYcmd);
    LCD_CTR.WriteData8(DrawPoint_Y >> 8);
    LCD_CTR.WriteData8(DrawPoint_Y & 0XFF);
    
    LCD_CTR.SelectReg(LCD_CTR.GRAMcmd);                   
    LCD_CTR.WriteData(DrawPoint_color);              
  
}


