/*--------------------------------------------------------------------------------------
*  @file     LCDSetup.c
*  @author   ZhangJing
*  @version  base on stm32f0x   
*  @date     2015.09.11
*  @brief    LCD驱动
---------------------------------------------------------------------------------------*/

#include "stm32f10x_gpio.h"
#include "TypeDefine.h"
#include "Driver.h"
#include "LCDSetup.h"
#include "SPISetup.h"
// #include "font.h"

/*************************************************************************************
*  Function:	LCDReset						                                                           
*  Object:		LCD重启
*  输入:			无
*  输出:			无	                                     
*  备注:			             
**************************************************************************************/
void LCDReset( void )
{
// 	#ifndef OLD_LCD
// 	LCD_ERD_CLR;
// 	LCD_RWR_CLR;
// 	#endif
	LCD_RST_CLR;
	Delay_ms(100);
	LCD_RST_SET;
	Delay_ms(50);
}

/****************************************************************************
* 名    称：void ili9220B_WriteIndex(u16 idx)
* 功    能：写 ili9220B 控制器寄存器地址
* 入口参数：idx   寄存器地址
* 出口参数：无
* 说    明：调用前需先选中控制器，内部函数
****************************************************************************/
void LCDWriteIndex( uint8_t index )
{
   //SPI 写命令时序开始
   LCD_CS_CLR;
   LCD_RS_CLR;
   SPIWriteByte(index);
}

/****************************************************************************
* 名    称：LCDWriteData
* 功    能：写LCD寄存器数据
* 入口参数：uint8_t Data寄存器数据
* 出口参数：无
* 说    明：向控制器指定地址写入数据，调用前需先写寄存器地址，内部函数
****************************************************************************/
void LCDWriteData( uint8_t Data )
{
   LCD_CS_CLR;
   LCD_RS_SET;
   SPIWriteByte(Data);
   LCD_CS_SET; 
}

/****************************************************************************
* 名    称：LCDWriteData16Bit
* 功    能：写LCD寄存器数据
* 入口参数：uint8_t DataH,uint8_t DataL寄存器数据
* 出口参数：无
* 说    明：向控制器指定地址写入数据
****************************************************************************/
void LCDWriteData16Bit( uint8_t DataH,uint8_t DataL )
{
	LCDWriteData(DataH);
	LCDWriteData(DataL);
}

/*************************************************
函数名：LCDSetRegion
功能：设置lcd显示区域，在此区域写点数据自动换行
入口参数：xy起点和终点
返回值：无
*************************************************/
#ifdef OLD_LCD
void LCDSetRegion( uint16_t x_start,uint16_t y_start,uint16_t x_end,uint16_t y_end )
{	
	LCDWriteIndex( 0x2a );
	LCDWriteData16Bit( x_start>>8,x_start );
	LCDWriteData16Bit( x_end>>8,x_end );
	LCDWriteIndex( 0x2b );
	LCDWriteData16Bit( y_start>>8,y_start );
	LCDWriteData16Bit( y_end>>8,y_end );
	LCDWriteIndex( 0x2c );
}
#else
void LCDSetRegion( uint16_t x_start,uint16_t y_start,uint16_t x_end,uint16_t y_end )
{	
	LCDWriteIndex( 0x40 );
	LCDWriteIndex( 0xb0 );//Y
	LCDWriteIndex( 0x10 );//XH
	LCDWriteIndex( 0x00 );//XL
	LCDWriteData16Bit( x_start>>8,x_start );
	LCDWriteData16Bit( x_end>>8,x_end );
	LCDWriteIndex( 0xb0 );//Y
	LCDWriteIndex( 0x10 );//XH
	LCDWriteIndex( 0x00 );//XL
	LCDWriteData16Bit( y_start>>8,y_start );
	LCDWriteData16Bit( y_end>>8,y_end );
}
#endif
    
/*************************************************************************************
*  Function:	LCDInit						                                                           
*  Object:		LCD初始化
*  输入:			无
*  输出:			无	                                     
*  备注:			             
**************************************************************************************/
void LCDInit( void )
{
	LCDReset();
	LCDWriteIndex(0xE2); //软件复位
	LCDWriteIndex(0xA2); //设置偏压比
	LCDWriteIndex(0xA1); //段扫描顺序:普通顺序
	LCDWriteIndex(0xC8); //行扫描顺序:反向顺序
	LCDWriteIndex(0x27); //校准比率设置
	
	LCDWriteIndex(0xF8); //软件复位
	LCDWriteIndex(0x00); //设置偏压比
	LCDWriteIndex(0x81); //段扫描顺序:普通顺序
	LCDWriteIndex(0x54); //行扫描顺序:反向顺序
	LCDWriteIndex(0x2C); //校准比率设置
	LCDWriteIndex(0x2E); //软件复位
	LCDWriteIndex(0x2F); //设置偏压比
	LCDWriteIndex(0x40); //段扫描顺序:普通顺序
	LCDWriteIndex(0xB0); //行扫描顺序:反向顺序
	LCDWriteIndex(0x10); //校准比率设置
	LCDWriteIndex(0x00); //行扫描顺序:反向顺序
	LCDWriteIndex(0xAF); //校准比率设置
}

/*************************************************************************************
*  Function:	LCDClear						                                                           
*  Object:		全屏清屏函数
*  输入:			填充颜色COLOR
*  输出:			无	                                     
*  备注:			             
**************************************************************************************/
void LCDClear( uint16_t Color )               
{	
	uint8_t i,j;
	LCDWriteIndex( 0x40 );
	for(i=0;i<9;i++)
	{		
		LCDWriteIndex( 0xb0 | i );		
		
		for( j = 0 ; j < 131 ; j++ )
		{			
			LCDWriteIndex( 0x10 | ( j >> 4 ) );
			LCDWriteIndex( 0x00 | ( j & 0x0f ) );
			LCDWriteData( 0 );
			LCDWriteData( 0 );
		}
	} 
}

/*************************************************************************************
*  Function:	LCDPartClear						                                                           
*  Object:		选择部分清屏函数
*  输入:			uint8_t startX , uint8_t endX , uint8_t y , uint8_t yCounts
*  输出:			无	                                     
*  备注:			输入要清屏的Y轴坐标，X轴的起始和结束坐标，每次清除时Y轴要清yCounts个段             
**************************************************************************************/
void LCDPartClear( uint8_t startX , uint8_t endX , uint8_t y , uint8_t yCounts )
{
	uint8_t i , j;
	for( j = 0 ; j < yCounts ; j++ )
	{
		LCDWriteIndex( 0xb0 | ( y - j ) );
		for( i = startX ; i < endX ; i++ )
		{
			LCDWriteIndex( 0x10 | ( i >> 4 ) );
			LCDWriteIndex( 0x00 | ( i & 0x0f ) );
			LCDWriteData( 0 );
			LCDWriteData( 0 );
		}
	}
}

/*************************************************
函数名:		LCD_Set_XY
功能:			设置lcd显示起始点,y表示的是页号共9页
入口参数:	x、y坐标
返回值:		无
*************************************************/
void LCDSetXY( uint16_t x,uint16_t y )
{	
	LCDWriteIndex( 0x40 );//set start line
	LCDWriteIndex( 0xb0 | y );//set page address,标头显示在第8页，其它内容显示在0~7页（页从0~8共9页）
	LCDWriteIndex( 0x10 | ( x >> 4 ) );//set column address MSB,设置X轴坐标
	LCDWriteIndex( 0x00 | ( x & 0x0f ) );//set column address LSB,设置X轴坐标
}

/*************************************************************************************
*  Function:	DisplayHeader						                                                           
*  Object:		段头显示
*  输入:			 uint8_t DataH,uint8_t DataL,uint16_t x
*  输出:			无	                                     
*  备注:			输入要显示段的的X轴坐标，确定此段后开始显示数据          
**************************************************************************************/
void DisplayHeader( uint8_t DataH,uint8_t DataL,uint16_t x )
{
	uint8_t j;
	LCDWriteIndex( 0x40 );//set start line
	LCDWriteIndex( 0xb8 );//set page address,标头显示在第9页（页从0~8共9页）
	LCDWriteIndex( 0x10 | ( x >> 4 ) );//set column address MSB,设置X轴坐标
	LCDWriteIndex( 0x00 | ( x & 0x0f ) );//set column address LSB,设置X轴坐标
	for( j = 0; j < 5; j++ )
	{			
		LCDWriteData(DataH);
		LCDWriteData(DataL);
	}
}

// void DisplayGraphics( uint16_t x,uint8_t y,uint8_t* data,uint8_t yQTY )
// {
// 	uint8_t i;
// 	LCDWriteIndex( 0x40 );//set start line
// 	LCDWriteIndex( 0xb0 | y );//set page address,标头显示在第9页（页从0~8共9页）
// 	LCDWriteIndex( 0x10 | ( x >> 8 ) );//set column address MSB,设置X轴坐标
// 	LCDWriteIndex( 0x00 | (uint8_t)x );//set column address LSB,设置X轴坐标
// }

/*************************************************************************************
*  Function:	DisplayGraphicsGBK24			                                                           
*  Object:		LCD页面显示函数
*  输入:			X Y轴坐标 所需要显示的数据 
*  输出:			无	                                     
*  备注:			因为屏的抬头应该在整个屏的上方，现在抬头在屏的最下方，是反过来的，为了与
							抬头匹配，所以显示时也是反向显示的，Y轴一个汉字需显示3页，方向是从7~0共
							8页可用，X轴起点从127~0，显示128bit
**************************************************************************************/
void DisplayGraphicsGBK24( uint16_t x,uint8_t y,uint8_t *gph )
{	
	uint8_t i,j;
//	uint8_t tempX = x;
 	LCDWriteIndex( 0x40 );
// 	for( i = 0; i < 3; i++ )//24点阵，每页有8个点阵，所以Y轴要有3页显示一个字
// 	{
// 		tempX = x;
// 		LCDWriteIndex( 0xb0 | ( y - i ) );
// 		for( j = 24; j > 0; j-- )
// 		{
// 			LCDWriteIndex( 0x10 | ( tempX >> 4 ) );
// 			LCDWriteIndex( 0x00 | ( tempX & 0x0f ) );
// 			LCDWriteData( *( gph + j - 1 ) );			
// 			tempX++;
// 		}
// 		gph += 24;
// 	}
	
	/*正向显示，修改时还需将字库改为 宋体 24点阵 纵向8点向下高位*/
	for( i = 0; i < 3; i++ )
	{
		LCDWriteIndex( 0xb0 | ( y - i ) );
		LCDWriteIndex( 0x10 | ( x >> 8 ) );
		LCDWriteIndex( 0x00 | ( (uint8_t) x ) );
		for( j = 0; j < 24; j++ )
		{
			LCDWriteData( *gph );
			gph++;
		}
	}
}

/*************************************************************************************
*  Function:	DisplayGraphicsGBK16			                                                           
*  Object:		LCD页面显示函数
*  输入:			X Y轴坐标 所需要显示的数据 
*  输出:			无	                                     
*  备注:			因为屏的抬头应该在整个屏的上方，现在抬头在屏的最下方，是反过来的，为了与
							抬头匹配，所以显示时也是反向显示的，Y轴一个汉字需显示两页，方向是从7~0共
							8页可用，X轴起点从127~0，显示128bit
**************************************************************************************/
void DisplayGraphicsGBK16( uint16_t x,uint8_t y,uint8_t *gph )
{
	uint8_t i,j;
//	uint8_t tempX = x;
 	LCDWriteIndex( 0x40 );
// 	for( i = 0; i < 2; i++ )//16点阵，每页有8个点阵，所以Y轴要有2页显示一个字
// 	{
// 		tempX = x;
// 		LCDWriteIndex( 0xb0 | ( y - i ) );
// 		for( j = 16; j > 0; j-- )
// 		{
// 			LCDWriteIndex( 0x10 | ( tempX >> 4 ) );
// 			LCDWriteIndex( 0x00 | ( tempX & 0x0f ) );
// 			LCDWriteData( *( gph + j - 1 ) );			
// 			tempX++;
// 		}
// 		gph += 16;
// 	}
	
	/*正向显示，修改时还需将字库改为 宋体 16点阵 纵向8点向下高位*/
	for( i = 0; i < 2; i++ )//16点阵，每页有8个点阵，所以Y轴要有2页显示一个字
	{
		LCDWriteIndex( 0xb0 | ( y - i ) );
		LCDWriteIndex( 0x10 | ( x >> 4 ) );
		LCDWriteIndex( 0x00 | ( x & 0x0f ) );
		for( j = 0; j < 16; j++ )
		{
			LCDWriteData( *gph );
			gph++;
		}
	}
}

/*************************************************************************************
*  Function:	DisplayGraphicsGBK12			                                                           
*  Object:		LCD页面显示函数
*  输入:			X Y轴坐标 所需要显示的数据 
*  输出:			无	                                     
*  备注:			因为屏的抬头应该在整个屏的上方，现在抬头在屏的最下方，是反过来的，为了与
							抬头匹配，所以显示时也是反向显示的，Y轴一个汉字需显示两页，方向是从7~0共
							8页可用，X轴起点从127~0，显示128bit
**************************************************************************************/
void DisplayGraphicsGBK12( uint16_t x,uint8_t y,uint8_t *gph )
{
	uint8_t i,j;
//	uint8_t tempX = x;
 	LCDWriteIndex( 0x40 );
// 	for( i = 0; i < 2; i++ )//12点阵，每页有8个点阵，所以Y轴要有2页显示一个字
// 	{
// 		tempX = x;
// 		LCDWriteIndex( 0xb0 | ( y - i ) );
// 		for( j = 12; j > 0; j-- )
// 		{
// 			LCDWriteIndex( 0x10 | ( tempX >> 4 ) );
// 			LCDWriteIndex( 0x00 | ( tempX & 0x0f ) );
// 			LCDWriteData( *( gph + j - 1 ) );			
// 			tempX++;
// 		}
// 		gph += 12;
// 	}
	
	for( i = 0; i < 2; i++ )//12点阵，每页有8个点阵，所以Y轴要有2页显示一个字
	{
		LCDWriteIndex( 0xb0 | ( y - i ) );
		LCDWriteIndex( 0x10 | ( x >> 4 ) );
		LCDWriteIndex( 0x00 | ( x & 0x0f ) );
		for( j = 0; j < 12; j++ )
		{
			LCDWriteData( *gph );
			gph++;
		}
	}
}

/*************************************************************************************
*  Function:	DisplayGraphicsGBK8_8			                                                           
*  Object:		LCD页面显示函数
*  输入:			X Y轴坐标 所需要显示的数据 
*  输出:			无	                                     
*  备注:			因为屏的抬头应该在整个屏的上方，现在抬头在屏的最下方，是反过来的，为了与
							抬头匹配，所以显示时也是反向显示的，Y轴一个ASCII码需显示1页，方向是从7~0共
							8页可用，X轴起点从127~0，显示128bit
**************************************************************************************/
void DisplayGraphicsGBK8_8( uint16_t x,uint8_t y,uint8_t *gph )
{
	uint8_t i,j;
	uint8_t tempX = x;
 	LCDWriteIndex( 0x40 );	
	
// 	for( i = 0; i < 1; i++ )//8点阵，每页有8个点阵，所以Y轴要有2页显示一个字
// 	{
// 		tempX = x;
// 		LCDWriteIndex( 0xb0 | ( y - i) );
// 		for( j = 5; j > 0; j-- )
// 		{
// 			LCDWriteIndex( 0x10 | ( tempX >> 4 ) );
// 			LCDWriteIndex( 0x00 | ( tempX & 0x0f ) );
// 			LCDWriteData( *( gph + j - 1 ) );			
// 			tempX++;
// 		}
// // 		gph += 6;
// 	}
	
	for( i = 0; i < 1; i++ )//8点阵，每页有8个点阵，所以Y轴要有1页显示一个字
	{
		tempX = x;
		LCDWriteIndex( 0xb0 | ( y - i ) );
		LCDWriteIndex( 0x10 | ( tempX >> 4 ) );
		LCDWriteIndex( 0x00 | ( tempX & 0x0f ) );
		for( j = 0; j < 5; j++ )
		{
			LCDWriteData( *gph );
			gph++;
			tempX++;
		}
	}
}

/*************************************************************************************
*  Function:	DisplayGraphicsGBK8_12			                                                           
*  Object:		LCD页面显示函数
*  输入:			X Y轴坐标 所需要显示的数据 
*  输出:			无	                                     
*  备注:			因为屏的抬头应该在整个屏的上方，现在抬头在屏的最下方，是反过来的，为了与
							抬头匹配，所以显示时也是反向显示的，Y轴一个ASCII码需显示1页，方向是从7~0共
							8页可用，X轴起点从127~0，显示128bit
**************************************************************************************/
void DisplayGraphicsGBK8_12( uint16_t x,uint8_t y,uint8_t *gph )
{
	uint8_t i,j;
	uint8_t tempX = x;
 	LCDWriteIndex( 0x40 );	
	
// 	for( i = 0; i < 2; i++ )//12点阵，每页有8个点阵，所以Y轴要有2页显示一个字
// 	{
// 		tempX = x;
// 		LCDWriteIndex( 0xb0 | ( y - i) );
// 		for( j = 6; j > 0; j-- )
// 		{
// 			LCDWriteIndex( 0x10 | ( tempX >> 4 ) );
// 			LCDWriteIndex( 0x00 | ( tempX & 0x0f ) );
// 			LCDWriteData( *( gph + j - 1 ) );			
// 			tempX++;
// 		}
// 		gph += 6;
// 	}
	
	for( i = 0; i < 2; i++ )//8点阵，每页有8个点阵，所以Y轴要有1页显示一个字
	{
		tempX = x;
		LCDWriteIndex( 0xb0 | ( y - i ) );
		LCDWriteIndex( 0x10 | ( tempX >> 4 ) );
		LCDWriteIndex( 0x00 | ( tempX & 0x0f ) );
		for( j = 0; j < 6; j++ )
		{
			LCDWriteData( *gph );
			gph++;
			tempX++;
		}
	}
}

/*************************************************************************************
*  Function:	DisplayGraphicsGBK8_16			                                                           
*  Object:		LCD页面显示函数
*  输入:			X Y轴坐标 所需要显示的数据 
*  输出:			无	                                     
*  备注:			因为屏的抬头应该在整个屏的上方，现在抬头在屏的最下方，是反过来的，为了与
							抬头匹配，所以显示时也是反向显示的，Y轴一个ASCII码需显示1页，方向是从7~0共
							8页可用，X轴起点从127~0，显示128bit
**************************************************************************************/
void DisplayGraphicsGBK8_16( uint16_t x,uint8_t y,uint8_t *gph )
{
	uint8_t i,j;
	uint8_t tempX = x;
 	LCDWriteIndex( 0x40 );	

// 	for( i = 0; i < 2; i++ )//16点阵，每页有8个点阵，所以Y轴要有2页显示一个字
// 	{
// 		tempX = x;
// 		LCDWriteIndex( 0xb0 | ( y - i ) );
// 		for( j = 8; j > 0; j-- )
// 		{
// 			LCDWriteIndex( 0x10 | ( tempX >> 4 ) );
// 			LCDWriteIndex( 0x00 | ( tempX & 0x0f ) );
// 			LCDWriteData( *( gph + j - 1 ) );			
// 			tempX++;
// 		}
// 	}
	
	for( i = 0; i < 2; i++ )//8点阵，每页有8个点阵，所以Y轴要有1页显示一个字
	{
		tempX = x;
		LCDWriteIndex( 0xb0 | ( y - i ) );
		LCDWriteIndex( 0x10 | ( tempX >> 4 ) );
		LCDWriteIndex( 0x00 | ( tempX & 0x0f ) );
		for( j = 0; j < 8; j++ )
		{
			LCDWriteData( *gph );
			gph++;
			tempX++;
		}
	}
}
