/*****************************************************************************
 *  Solomon Systech. SSD1963 LCD controller driver
 *****************************************************************************
 * FileName:        SSD1963.c
 * Processor:       STM32F10X
 * Compiler:       	RealView MDK
 * Company:			PowerMCU Company
 * Remarks:			
 *					 
 * Versions:        1.0
 *
 * Author:          PowerAVR 	    2010/06/03
 * www.PowerMCU.com
 * www.PowerAVR.com
******************************************************************************/
#include "SSD1963.h"
#include "AsciiLib_65k.h"
// Color
u32  _color;
// Clipping region control
u16 _clipRgn;
// Clipping region borders
u16 _clipLeft;
u16 _clipTop;
u16 _clipRight;
u16 _clipBottom;

// Active Page
u8  _activePage;
// Visual Page
u8  _visualPage;

// ssd1963 specific
u8 _gpioStatus = 0;

/* If processor works on high frequency delay has to be increased, it can be 
   increased by factor 2^N by this constant                                   */
#define DELAY_2N    18

/*******************************************************************************
* Delay in while loop cycles                                                   *
*   Parameter:    cnt:    number of while cycles to delay                      *
*   Return:                                                                    *
*******************************************************************************/

void DelayMs (int cnt) 
{

  cnt <<= DELAY_2N;
  while (cnt--);
}

/*********************************************************************
* Function: Set a GPIO pin to state high(1) or low(0)
*
* PreCondition: Set the GPIO pin an output prior using this function
*
* Arguments: BYTE pin	- 	LCD_RESET
*							LCD_SPENA
*							LCD_SPCLK
*							LCD_SPDAT	defined under GraphicsConfig.h
*							
*			 BOOL state - 	0 for low
*							1 for high
* Return: none
*
* Note:
*********************************************************************/
void GPIO_WR(u8 pin, u8 state)
{
	if(state==1)
		_gpioStatus = _gpioStatus|pin;
	else
		_gpioStatus = _gpioStatus&(~pin);

	WriteCommand(0xBA);				// Set GPIO value
	WriteData(_gpioStatus);
}

/*********************************************************************
* Function: 
*
* PreCondition: GPIO pins for the SPI port set all output prior to 
*               using this function
* Arguments:
*
* Return: none
*
* Note:
*********************************************************************/
void SPI_Write(u8 byte)
{
	u8 bit_ctr;

	for(bit_ctr=0; bit_ctr<8; bit_ctr++)
	{
		if(byte&0x80)
			GPIO_WR(LCD_SPDAT,1);
		else
			GPIO_WR(LCD_SPDAT,0);

		GPIO_WR(LCD_SPCLK,0);
		GPIO_WR(LCD_SPCLK,1);
		byte=(byte<<1);
	}
}

/*********************************************************************
* Function: 
*
* PreCondition: GPIO pins for the SPI port set all output prior to 
*               using this function
* Arguments:
*
* Return: none
*
* Note:
*********************************************************************/
void SPI_SetReg(u8 reg, u16 cmd)
{
/*	GPIO_WR(LCD_SPENA,0);	// RS=0 for index read/write, RS=1 for instruction read/write
	SPI_Write(0x70);	// This is a bitwise for (Device ID|RS|RW), therefore 0b011100|RS|RW, with RS=0, RW=0
	SPI_Write(0x00);	// register in 0x00[reg]
	SPI_Write(reg);
	GPIO_WR(LCD_SPENA,1);

	GPIO_WR(LCD_SPENA,0);	
	SPI_Write(0x72);	// Now RS=1 & RW=0 for command set
	SPI_Write(((u8)cmd)>>8);
	SPI_Write(((u8)cmd));
	GPIO_WR(LCD_SPENA,1);	   */

	u16	 temp = reg;

	GPIO_WR(LCD_SPENA,0);
	cmd = ((temp << 10) |(1 << 9) |cmd);
	SPI_Write(((u8)(cmd)>>8));
	SPI_Write(((u8)cmd));
	GPIO_WR(LCD_SPENA,1);
}

/*******************************************************************************
* Function Name  : LCD_CtrlLinesConfig
* Description    : Configures LCD Control lines (FSMC Pins) in alternate function
                   Push-Pull mode.
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
static void LCD_CtrlLinesConfig(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Enable FSMC, GPIOD, GPIOE and AFIO clocks */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO, ENABLE);
                        
  /* 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) */
  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_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOE, &GPIO_InitStructure);

  /* PD.00(D2), PD.01(D3), PD.04(RD), PD.5(WR), PD.7(CS), PD.8(D13), PD.9(D14),
     PD.10(D15), PD.11(RS) PD.14(D0) PD.15(D1) */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 | 
                                 GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | 
                                 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);
}

/*******************************************************************************
* Function Name  : LCD_FSMCConfig
* Description    : Configures the Parallel interface (FSMC) for LCD(Parallel mode)
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
static void LCD_FSMCConfig(void)
{
  FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
  FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructure;

  FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = 30;  /* 地址建立时间  */
  FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 0;	   
  FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = 30;	   /* 数据建立时间  */
  FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration = 0x00;
  FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 0x00;
  FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0x00;
  FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_A;	/* FSMC 访问模式 */

  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
  FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;
  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_Enable;
  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;

  FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = 3;  /* 地址建立时间  */
  FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 0;	   
  FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = 3;	   /* 数据建立时间  */
  FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration = 0x00;
  FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 0x00;
  FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0x00;
  FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_A;	/* FSMC 访问模式 */

  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;	  

  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); 

  /* Enable FSMC Bank1_SRAM Bank */
  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);  
}

/*******************************************************************************
* Function Name  : LCD_Configuration
* Description    : Configure the LCD Control pins and FSMC Parallel interface
* Input          : None
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
static void LCD_Configuration(void)
{
 /* Configure the LCD Control pins --------------------------------------------*/
  LCD_CtrlLinesConfig();

/* Configure the FSMC Parallel interface -------------------------------------*/
  LCD_FSMCConfig();
}

/*********************************************************************
* Function:  void ResetDevice()
*
* PreCondition: none
*
* Input: none
*
* Output: none
*
* Side Effects: none
*
* Overview: Resets LCD, initializes FSMC
*			Initialize low level IO port for mcu,
*			initialize SSD1963 for PCLK,
*			HSYNC, VSYNC etc
*
* Note: Need to set the backlight intensity by SetBacklight(BYTE intensity)
*		in main()
*
********************************************************************/
void ResetDevice(void)
{
	LCD_Configuration();
	//Set MN(multipliers) of PLL, VCO = crystal freq * (N+1)
	//PLL freq = VCO/M with 250MHz < VCO < 800MHz
	//The max PLL freq is around 120MHz. To obtain 120MHz as the PLL freq
	WriteCommand(0xE2);				// Set PLL with OSC = 10MHz (hardware)
									// Multiplier N = 35, VCO (>250MHz)= OSC*(N+1), VCO = 360MHz
	WriteData(0x23);
	WriteData(0x02);				// Divider M = 2, PLL = 360/(M+1) = 120MHz
	WriteData(0x54);				// Validate M and N values	

	WriteCommand(0xE0);				// Start PLL command
	WriteData(0x01);				// enable PLL	

	DelayMs(10);						// wait stablize
	WriteCommand(0xE0);				// Start PLL command again
	WriteData(0x03);				// now, use PLL output as system clock		
	//once PLL locked (at 120MHz), the data hold time set shortest

	WriteCommand(0x01);				// Soft reset
	DelayMs(10);

    /*
	***********************************
	* 4.3" TFT panel model # TYX430TFT480272
	***********************************
	*/
#if (DISPLAY_PANEL==TYX430TFT480272)	
	//Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
	//Typical DCLK for TYX430TFT480272 is 9MHz
	//9MHz = 120MHz*(LCDC_FPR+1)/2^20
	//LCDC_FPR = 78642 (0x13332)
	WriteCommand(0xE6);
	WriteData(0x01);
	WriteData(0x33);
	WriteData(0x32);
	/*
	****************************************************************
	* 7" TFT model # TYX700TFT800480
	****************************************************************
	*/
#elif (DISPLAY_PANEL==TYX700TFT800480)
	//Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
	//Typical DCLK for TYX700TFT800480 is 33.3MHz(datasheet), experiment shows 30MHz gives a stable result
	//30MHz = 120MHz*(LCDC_FPR+1)/2^20
	//LCDC_FPR = 262143 (0x3FFFF)
	//Time per line = (DISP_HOR_RESOLUTION+DISP_HOR_PULSE_WIDTH+DISP_HOR_BACK_PORCH+DISP_HOR_FRONT_PORCH)/30 us = 1056/30 = 35.2us
	WriteCommand(0xE6);
	WriteData(0x03);
	WriteData(0xff);
	WriteData(0xff);	
	/*
	***********************************
	* 3.5" TFT model # TYX350TFT320240
	***********************************
	*/
#elif (DISPLAY_PANEL==TYX350TFT320240)
	//Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
	//Typical DCLK for TYX350TFT320240 is 6.5MHz in 24 bit format
	//6.5MHz = 120MHz*(LCDC_FPR+1)/2^20
	//LCDC_FPR = 56796 (0x00DDDC)
	WriteCommand(0xE6);
	WriteData(0x00);
	WriteData(0xDD);
	WriteData(0xDC);
#endif
	
	//Set panel mode, varies from individual manufacturer
	WriteCommand(0xB0);
#if ((DISPLAY_PANEL==TYX430TFT480272)||(DISPLAY_PANEL==TYX350TFT320240))
	WriteData(0x20);				// set 24-bit for TYX430TF480272 4.3" panel or TYX350TFT320240 3.5" TFT Panel
	WriteData(0x00);				// set Hsync+Vsync mode
	WriteData((DISP_HOR_RESOLUTION-1)>>8&0x07); //Set panel size
	WriteData((DISP_HOR_RESOLUTION-1)&0xff);
	WriteData((DISP_VER_RESOLUTION-1)>>8&0x07);
	WriteData((DISP_VER_RESOLUTION-1)&0xff);
	WriteData(0x00);				//RGB sequence
#elif (DISPLAY_PANEL==TYX700TFT800480)
	WriteData(0x10);				// set 18-bit for 7" panel TYX700TFT800480
	WriteData(0x80);				// set TTL mode
	WriteData((DISP_HOR_RESOLUTION-1)>>8); //Set panel size
	WriteData(DISP_HOR_RESOLUTION-1);
	WriteData((DISP_VER_RESOLUTION-1)>>8);
	WriteData(DISP_VER_RESOLUTION-1);
	WriteData(0x00);				//RGB sequence	
#endif


	//Set horizontal period
	WriteCommand(0xB4);
	#define HT (DISP_HOR_RESOLUTION+DISP_HOR_PULSE_WIDTH+DISP_HOR_BACK_PORCH+DISP_HOR_FRONT_PORCH)
	WriteData((HT-1)>>8);	
	WriteData(HT-1);
	#define HPS (DISP_HOR_PULSE_WIDTH+DISP_HOR_BACK_PORCH)
	WriteData((HPS-1)>>8);
	WriteData(HPS-1);
	WriteData(DISP_HOR_PULSE_WIDTH-1);
	WriteData(0x00);
	WriteData(0x00);
	WriteData(0x00);

	//Set vertical period
	WriteCommand(0xB6);
	#define VT (DISP_VER_PULSE_WIDTH+DISP_VER_BACK_PORCH+DISP_VER_FRONT_PORCH+DISP_VER_RESOLUTION)
	WriteData((VT-1)>>8);
	WriteData(VT-1);
	#define VSP (DISP_VER_PULSE_WIDTH+DISP_VER_BACK_PORCH)
	WriteData((VSP-1)>>8);
	WriteData(VSP-1);
	WriteData(DISP_VER_PULSE_WIDTH-1);
	WriteData(0x00);
	WriteData(0x00);
	
	//Set pixel format, i.e. the bpp
/*	WriteCommand(0x3A);
	WriteData(0x55); 				// set 16bpp			   */

	//Set pixel data interface
	WriteCommand(0xF0);
#ifdef USE_16BIT_PMP
	WriteData(0x03);				//16-bit(565 format) data for 16bpp PIC32MX only
#else
	WriteData(0x00);				//8-bit data for 16bpp, PIC24 series
#endif

#if (DISPLAY_PANEL==TYX350TFT320240)
	WriteCommand(0xB8);				// Set all GPIOs to output, controlled by host
	WriteData(0x0f);				// Set GPIO0 as output
	WriteData(0x01);				// GPIO[3:0] used as normal GPIOs

	// LL Reset to LCD!!!
	GPIO_WR(LCD_SPENA, 1);
	GPIO_WR(LCD_SPCLK, 1);
	GPIO_WR(LCD_SPDAT,1);
	GPIO_WR(LCD_RESET,1);
	GPIO_WR(LCD_RESET,0);
	DelayMs(1);
	GPIO_WR(LCD_RESET,1);
#endif

#if (DISPLAY_PANEL==TYX350TFT320240)
	SPI_SetReg(0x00,0x07);
	SPI_SetReg(0x01,0x00);
	SPI_SetReg(0x02,0x03);
	SPI_SetReg(0x03,0xcc);
	SPI_SetReg(0x04,0x46);
	SPI_SetReg(0x05,0x0d);
	SPI_SetReg(0x06,0x00);
	SPI_SetReg(0x07,0x00);
	SPI_SetReg(0x08,0x08);
	SPI_SetReg(0x09,0x40);
	SPI_SetReg(0x0a,0x88);
	SPI_SetReg(0x0b,0x88);
	SPI_SetReg(0x0c,0x30);
	SPI_SetReg(0x0d,0x20);
	SPI_SetReg(0x0e,0x6a);
	SPI_SetReg(0x0f,0xa4);
	SPI_SetReg(0x10,0x04);
	SPI_SetReg(0x11,0x24);
	SPI_SetReg(0x12,0x24);
	SPI_SetReg(0x1e,0x00);
	SPI_SetReg(0x20,0x00);				
	
#endif

	WriteCommand(0x29);				// Turn on display; show the image on display		
}

/*********************************************************************
* Function:  SetArea(start_x,start_y,end_x,end_y)
*
* PreCondition: SetActivePage(page)
*
* Input: start_x, end_x	- start column and end column
*		 start_y,end_y 	- start row and end row position (i.e. page address)
*
* Output: none
*
* Side Effects: none
*
* Overview: defines start/end columns and start/end rows for memory access
*			from host to SSD1963
* Note: none
********************************************************************/
void SetArea(u16 start_x, u16 start_y, u16 end_x, u16 end_y)
{
	u32 offset;

	offset = (u16)_activePage*(GetMaxY()+1);

	start_y = offset + start_y;
	end_y   = offset + end_y;

	WriteCommand(CMD_SET_COLUMN);
	WriteData(start_x>>8);
	WriteData(start_x);
	WriteData(end_x>>8);
	WriteData(end_x);
	
	WriteCommand(CMD_SET_PAGE);
	WriteData(start_y>>8);
	WriteData(start_y);
	WriteData(end_y>>8);
	WriteData(end_y);
}

/*********************************************************************
* Macros:  WriteCommand(cmd)
*
* PreCondition: 
*
* Input: cmd - controller command
*
* Output: none
*
* Side Effects: none
*
* Overview: writes command
*
* Note: none
********************************************************************/
void WriteCommand(uint16_t cmd)
{ 
	/* Write cmd */
  LCD_REG = cmd;	
} 

void WriteData(uint16_t data)
{ 
	/* Write 16-bit data */
  LCD_RAM = data;
} 

uint16_t ReadData(void)
{
	/* Read 16-bit data */
  return LCD_RAM;
}

/*********************************************************************
* Function:  void  SetBacklight(BYTE intensity)
*
* Overview: This function makes use of PWM feature of ssd1963 to adjust
*			the backlight intensity. 
*
* PreCondition: Backlight circuit with shutdown pin connected to PWM output of ssd1963.
*
* Input: 	(BYTE) intensity from 
*			0x00 (total backlight shutdown, PWM pin pull-down to VSS)
*			0xff (99% pull-up, 255/256 pull-up to VDD)
*
* Output: none
*
* Note: The base frequency of PWM set to around 300Hz with PLL set to 120MHz.
*		This parameter is hardware dependent
********************************************************************/
void SetBacklight(uint8_t intensity)
{
	WriteCommand(0xBE);			// Set PWM configuration for backlight control
	WriteData(0x0E);			// PWMF[7:0] = 14, PWM base freq = PLL/(256*(1+14))/256 = 
								// 122Hz for a PLL freq = 120MHz
	WriteData(intensity);		// Set duty cycle, from 0x00 (total pull-down) to 0xFF 
								// (99% pull-up , 255/256)
	WriteData(0x01);			// PWM enabled and controlled by host (mcu)
	WriteData(0x00);
	WriteData(0x00);
	WriteData(0x00);
}

u16 PwmValue[6];

void GetBacklight(void)
{
	WriteCommand(0xBF);			// Set PWM configuration for backlight control
	PwmValue[0] = ReadData();			// PWMF[7:0] = 2, PWM base freq = PLL/(256*(1+5))/256 = 
								// 300Hz for a PLL freq = 120MHz
	PwmValue[1] = ReadData();		// Set duty cycle, from 0x00 (total pull-down) to 0xFF 
								// (99% pull-up , 255/256)
	PwmValue[2] = ReadData();			// PWM enabled and controlled by host (mcu)
	PwmValue[3] = ReadData();
	PwmValue[4] = ReadData();
	PwmValue[5] = ReadData();
}

void GetPllStatus(void)
{
	WriteCommand(0xE4);			
	PwmValue[0] = ReadData();			
}

/******************************************************************************
* Function Name  : LCD_GetPoint
* Description    : 获取指定座标的颜色值
* Input          : - Xpos: Row Coordinate
*                  - Xpos: Line Coordinate 
* Output         : None
* Return         : Screen Color
* Attention		 : None
*******************************************************************************/
uint16_t LCD_GetPoint(uint16_t Xpos,uint16_t Ypos)
{
    SetArea(Xpos,Ypos,GetMaxX(),GetMaxY());
	WriteCommand(CMD_RD_MEMSTART);
    return ( LCD_BGR2RGB(ReadData()) );
}

/******************************************************************************
* Function Name  : LCD_SetPoint
* Description    : 在指定座标画点
* Input          : - Xpos: Row Coordinate
*                  - Xpos: Line Coordinate 
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void LCD_SetPoint(uint16_t Xpos,uint16_t Ypos,uint16_t point)
{
  if(_clipRgn){
		if(Xpos<_clipLeft)
			return;
		if(Xpos>_clipRight)
			return;
		if(Ypos<_clipTop)
			return;
		if(Ypos>_clipBottom)
			return;
	}
  	
	SetArea(Xpos,Ypos,GetMaxX(),GetMaxY());
	WriteCommand(CMD_WR_MEMSTART);
	WriteData(point);
}

/*********************************************************************
* Function: void ClearDevice(void)
*
* PreCondition: none
*
* Input: none
*
* Output: none
*
* Side Effects: none
*
* Overview: clears screen with current color 
*
* Note: none
*
********************************************************************/
void ClearDevice(u16 color)
{
//	u32     counter;
	u32 xcounter, ycounter;

	SetArea(0,0,GetMaxX(),GetMaxY());

	WriteCommand(CMD_WR_MEMSTART);

	for(ycounter=0;ycounter<GetMaxY()+1;ycounter++)
	{
		for(xcounter=0;xcounter<GetMaxX()+1;xcounter++)
		{
			WriteData(color);
		}
	}		 
}

/******************************************************************************
* Function Name  : LCD_DrawPicture
* Description    : 在指定坐标范围显示一副图片
* Input          : - StartX: Row Start Coordinate 
*                  - StartY: Line Start Coordinate  
*				   - EndX: Row End Coordinate 
*				   - EndY: Line End Coordinate   
* Output         : None
* Return         : None
* Attention		 : 图片取模格式为水平扫描，16位颜色模式
*******************************************************************************/
void LCD_DrawPicture(uint16_t StartX,uint16_t StartY,uint16_t EndX,uint16_t EndY,uint16_t *pic)
{
  uint16_t  i;

  SetArea(0,0,GetMaxX(),GetMaxY());
  WriteCommand(CMD_WR_MEMSTART);
  for (i=0;i<(EndX*EndY);i++)
  {
      WriteData(*pic++);
  }
}

/******************************************************************************
* Function Name  : PutChar
* Description    : 将Lcd屏上任意位置显示一个字符
* Input          : - Xpos: 水平坐标 
*                  - Ypos: 垂直坐标  
*				   - c: 显示的字符
*				   - charColor: 字符颜色   
*				   - bkColor: 背景颜色 
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void PutChar(unsigned short Xpos,unsigned short Ypos,unsigned char c,unsigned short charColor,unsigned short bkColor)
{
  unsigned short i=0;
  unsigned short j=0;
  unsigned char buffer[16];
  unsigned char tmp_char=0;
  GetASCIICode(buffer,c);  /* 取字模数据 */
  for (i=0;i<16;i++)
  {
    tmp_char=buffer[i];
    for (j=0;j<8;j++)
    {
      if ( (tmp_char >> 7-j) & 0x01 == 0x01)
        {
          LCD_SetPoint(Xpos+j,Ypos+i,charColor);  /* 字符颜色 */
        }
        else
        {
          LCD_SetPoint(Xpos+j,Ypos+i,bkColor);  /* 背景颜色 */
        }
    }
  }
}

/******************************************************************************
* Function Name  : GUI_Text
* Description    : 在指定座标显示字符串
* Input          : - Xpos: 行座标
*                  - Ypos: 列座标 
*				   - str: 字符串
*				   - charColor: 字符颜色   
*				   - bkColor: 背景颜色 
* Output         : None
* Return         : None
* Attention		 : None
*******************************************************************************/
void GUI_Text(uint16_t Xpos, uint16_t Ypos, uint8_t *str,uint16_t Color, uint16_t bkColor)
{
uint8_t TempChar;
 do
  {
    TempChar=*str++;  
    PutChar(Xpos,Ypos,TempChar,Color,bkColor);    
    if (Xpos<472)
    {
      Xpos+=8;
    } 
    else if (Ypos<256)
    {
      Xpos=0;
      Ypos+=16;
    }   
    else
    {
      Xpos=0;
      Ypos=0;
    }    
  }
  while (*str!=0);
}

 /******************************************************************************
* Function Name  : LCD_BGR2RGB
* Description    : RRRRRGGGGGGBBBBB 改为 BBBBBGGGGGGRRRRR 格式
* Input          : - color: BRG 颜色值  
* Output         : None
* Return         : RGB 颜色值
* Attention		 : 内部函数调用
*******************************************************************************/
uint16_t LCD_BGR2RGB(uint16_t color)
{
  uint16_t  r, g, b, rgb;

  b = ( color>>0 )  & 0x1f;
  g = ( color>>5 )  & 0x3f;
  r = ( color>>11 ) & 0x1f;
 
  rgb =  (b<<11) + (g<<5) + (r<<0);

  return( rgb );
}
