#include "lcd.h"
#include "stdlib.h"
#include "usart.h"
#include "delay.h"	 
//////////////////////////////////////////////////////////////////////////////////	 
//本程序只供学习使用，未经作者许可，不得用于其它任何用途
//测试硬件：单片机STM32F103RBT6,主频72M  单片机工作电压3.3V
//QDtech-TFT液晶驱动 for STM32 IO模拟
//xiao冯@ShenZhen QDtech co.,LTD
//公司网站:www.qdtech.net
//淘宝网站：http://qdtech.taobao.com
//我司提供技术支持，任何技术问题欢迎随时交流学习
//固话(传真) :+86 0755-23594567 
//手机:15989313508（冯工） 
//邮箱:QDtech2008@gmail.com 
//Skype:QDtech2008
//技术交流QQ群:324828016
//创建日期:2013/5/13
//版本：V1.1
//版权所有，盗版必究。
//Copyright(C) 深圳市全动电子技术有限公司 2009-2019
//All rights reserved
/****************************************************************************************************
//=========================================电源接线================================================//
//5V接DC 5V电源
//GND接地
//=======================================液晶屏数据线接线==========================================//
//本模块默认数据总线类型为8位并行模式
//8位模式接线：8位模式9341模块接高8位总线，即:
//液晶屏LCD_D0对应单片机PB8
//液晶屏LCD_D1对应单片机PB9
//液晶屏LCD_D2对应单片机PB10
//液晶屏LCD_D3对应单片机PB11
//液晶屏LCD_D4对应单片机PB12
//液晶屏LCD_D5对应单片机PB13
//液晶屏LCD_D6对应单片机PB14
//液晶屏LCD_D7对应单片机PB15
//=======================================液晶屏控制线接线==========================================//
//LCD_RST	接PC5	//复位信号
//LCD_CS	接PC9	//片选信号
//LCD_RS	接PC8	//寄存器/数据选择信号
//LCD_WR	接PC7	//写信号
//LCD_RD	接PC6	//读信号
//=========================================触摸屏触接线=========================================//
//本模块触摸测试需连接外部XPT2046触摸采样芯片，所以本程序不进行触摸测试。
//不使用触摸或者模块本身不带触摸，则可不连接
**************************************************************************************************/	
	   
//管理LCD重要参数
//默认为竖屏
_lcd_dev lcddev;

//画笔颜色,背景颜色
u16 POINT_COLOR = 0x0000,BACK_COLOR = 0xFFFF;  
u16 DeviceCode;	 


//******************************************************************
//函数名：  LCD_WR_REG
//作者：    xiao冯@全动电子
//日期：    2013-02-22
//功能：    向液晶屏总线写入写16位指令
//输入参数：Reg:待写入的指令值
//返回值：  无
//修改记录：无
//******************************************************************
void LCD_WR_REG(u8 data)
{ 
#if LCD_USE8BIT_MODEL==1//使用8位并行数据总线模式
	LCD_RS_CLR;
	LCD_CS_CLR;
	DATAOUT(data<<8);
	LCD_WR_CLR;
	LCD_WR_SET;
	LCD_CS_SET;
	
#else//使用16位并行数据总线模式
	LCD_RS_CLR;
	LCD_CS_CLR;
	DATAOUT(data);
	LCD_WR_CLR;
	LCD_WR_SET;
	LCD_CS_SET;
			
#endif	
}

//******************************************************************
//函数名：  LCD_WR_DATA
//作者：    xiao冯@全动电子
//日期：    2013-02-22
//功能：    向液晶屏总线写入写16位数据
//输入参数：Data:待写入的数据
//返回值：  无
//修改记录：无
//******************************************************************
void LCD_WR_DATA(u16 data)
{
	

#if LCD_USE8BIT_MODEL==1//使用8位并行数据总线模式
	LCD_RS_SET;
	LCD_CS_CLR;
	DATAOUT(data<<8);
	LCD_WR_CLR;
	LCD_WR_SET;
	LCD_CS_SET;
	
#else//使用16位并行数据总线模式
	LCD_RS_SET;
	LCD_CS_CLR;
	DATAOUT(data);
	LCD_WR_CLR;
	LCD_WR_SET;
	LCD_CS_SET;
			
#endif

}
//******************************************************************
//函数名：  LCD_DrawPoint_16Bit
//作者：    xiao冯@全动电子
//日期：    2013-02-22
//功能：    8位总线下如何写入一个16位数据
//输入参数：(x,y):光标坐标
//返回值：  无
//修改记录：无
//******************************************************************
void LCD_DrawPoint_16Bit(u16 color)
{
#if LCD_USE8BIT_MODEL==1
	LCD_CS_CLR;
	LCD_RD_SET;
	LCD_RS_SET;//写地址  	 
	DATAOUT(color);	
	LCD_WR_CLR;
	LCD_WR_SET;	
	DATAOUT(color<<8);	
	LCD_WR_CLR;
	LCD_WR_SET;	 
	LCD_CS_SET;
#else
	LCD_WR_DATA(color); 
#endif


}

//******************************************************************
//函数名：  LCD_WriteReg
//作者：    xiao冯@全动电子
//日期：    2013-02-22
//功能：    写寄存器数据
//输入参数：LCD_Reg:寄存器地址
//			LCD_RegValue:要写入的数据
//返回值：  无
//修改记录：无
//******************************************************************
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)
{	
	LCD_WR_REG(LCD_Reg);  
	LCD_WR_DATA(LCD_RegValue);	    		 
}	   
	 
//******************************************************************
//函数名：  LCD_WriteRAM_Prepare
//作者：    xiao冯@全动电子
//日期：    2013-02-22
//功能：    开始写GRAM
//			在给液晶屏传送RGB数据前，应该发送写GRAM指令
//输入参数：无
//返回值：  无
//修改记录：无
//******************************************************************
void LCD_WriteRAM_Prepare(void)
{
	LCD_WR_REG(lcddev.wramcmd);
}	 

//******************************************************************
//函数名：  LCD_DrawPoint
//作者：    xiao冯@全动电子
//日期：    2013-02-22
//功能：    在指定位置写入一个像素点数据
//输入参数：(x,y):光标坐标
//返回值：  无
//修改记录：无
//******************************************************************
void LCD_DrawPoint(u16 x,u16 y)
{
	LCD_SetCursor(x,y);//设置光标位置 
#if LCD_USE8BIT_MODEL==1
	LCD_CS_CLR;
	LCD_RD_SET;
	LCD_RS_SET;//写地址  	 
	DATAOUT(POINT_COLOR);	
	LCD_WR_CLR;
	LCD_WR_SET;	
	DATAOUT(POINT_COLOR<<8);	
	LCD_WR_CLR;
	LCD_WR_SET;	 
	LCD_CS_SET;
#else
	LCD_WR_DATA(POINT_COLOR); 
#endif


}

//******************************************************************
//函数名：  LCD_Clear
//作者：    xiao冯@全动电子
//日期：    2013-02-22
//功能：    LCD全屏填充清屏函数
//输入参数：Color:要清屏的填充色
//返回值：  无
//修改记录：无
//******************************************************************
void LCD_Clear(u16 Color)
{
	u32 index=0;      
	LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);	
#if LCD_USE8BIT_MODEL==1
	LCD_RS_SET;//写数据 
	LCD_CS_CLR;	   
	for(index=0;index<lcddev.width*lcddev.height;index++)
	{
		DATAOUT(Color);	
		LCD_WR_CLR;
		LCD_WR_SET;	
		
		DATAOUT(Color<<8);	
		LCD_WR_CLR;
		LCD_WR_SET;	   
	}
	LCD_CS_SET;	
#else //16位模式
	for(index=0;index<lcddev.width*lcddev.height;index++)
	{
		LCD_WR_DATA(Color);		  
	}
#endif
	
} 

//******************************************************************
//函数名：  LCD_GPIOInit
//作者：    xiao冯@全动电子
//日期：    2013-02-22
//功能：    液晶屏IO初始化，液晶初始化前要调用此函数
//输入参数：无
//返回值：  无
//修改记录：无
//******************************************************************
void LCD_GPIOInit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); 
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_5;	   //GPIO_Pin_10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC	
	GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_5);


	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;	//  
	GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
	GPIO_SetBits(GPIOB,GPIO_Pin_All);	 
}

//******************************************************************
//函数名：  LCD_Reset
//作者：    xiao冯@全动电子
//日期：    2013-02-22
//功能：    LCD复位函数，液晶初始化前要调用此函数
//输入参数：无
//返回值：  无
//修改记录：无
//******************************************************************
void LCD_RESET(void)
{
	LCD_RST_CLR;
	delay_ms(100);	
	LCD_RST_SET;
	delay_ms(50);
}
 	 
//******************************************************************
//函数名：  LCD_Init
//作者：    xiao冯@全动电子
//日期：    2013-02-22
//功能：    LCD初始化
//输入参数：无
//返回值：  无
//修改记录：无
//******************************************************************
void LCD_Init(void)
{  
     										 
	LCD_GPIOInit();
 	LCD_RESET();

	//************* Start Initial Sequence **********//		
	LCD_WriteReg(0x2E, 0x89); //write_data(0x00,); //GDOFF
	LCD_WriteReg(0x29, 0X8F); //write_data(0x00); //RTN
	LCD_WriteReg(0x2B, 0X02); //write_data(0x00,); //DUM
	LCD_WriteReg(0xE2, 0X00); //write_data(0x00,); //VREF
	LCD_WriteReg(0xE4, 0X01); //write_data(0x00,); //EQ
	LCD_WriteReg(0xE5, 0X10); //write_data(0x00,); //EQ
	LCD_WriteReg(0xE6, 0X01); //write_data(0x00,); //EQ
	LCD_WriteReg(0xE7, 0X10); //write_data(0x00,); //EQ
	LCD_WriteReg(0xE8, 0X70); //write_data(0x00,); //OPON
	LCD_WriteReg(0xF2, 0X00); //write_data(0x00,); //GEN
	LCD_WriteReg(0xEA, 0X00); //write_data(0x00,); //PTBA
	LCD_WriteReg(0xEB, 0X20); //write_data(0x00,); //PTBA
	LCD_WriteReg(0xEC, 0X3C); //write_data(0x00,); //STBA
	LCD_WriteReg(0xED, 0XC8); //write_data(0x00,); //STBA
	LCD_WriteReg(0xE9, 0X38); //write_data(0x00,); //OPON1
	LCD_WriteReg(0xF1, 0X01); //write_data(0x00,); //OTPS1B
	// Gamma 2.8 setting 
	LCD_WriteReg(0x40, 0X00); //write_data(0x00,); //
	LCD_WriteReg(0x41, 0X00); //write_data(0x00,); //
	LCD_WriteReg(0x42, 0X00); //write_data(0x00,); //
	LCD_WriteReg(0x43, 0X15); //write_data(0x00,); //
	LCD_WriteReg(0x44, 0X13); //write_data(0x00,); //
	LCD_WriteReg(0x45, 0X3f); //write_data(0x00,); //
	LCD_WriteReg(0x47, 0X55); //write_data(0x00,); //
	LCD_WriteReg(0x48, 0X00); //write_data(0x00,); //
	LCD_WriteReg(0x49, 0X12); //write_data(0x00,); //
	LCD_WriteReg(0x4A, 0X19); //write_data(0x00,); //
	LCD_WriteReg(0x4B, 0X19); //write_data(0x00,); //
	LCD_WriteReg(0x4C, 0X16); //write_data(0x00,); //
	LCD_WriteReg(0x50, 0X00); //write_data(0x00,); //
	LCD_WriteReg(0x51, 0X2c); //write_data(0x00,); //
	LCD_WriteReg(0x52, 0X2a); //write_data(0x00,); //
	LCD_WriteReg(0x53, 0X3F); //write_data(0x00,); //
	LCD_WriteReg(0x54, 0X3F); //write_data(0x00,); //
	LCD_WriteReg(0x55, 0X3F); //write_data(0x00,); //
	LCD_WriteReg(0x56, 0X2a); //write_data(0x00,); //
	LCD_WriteReg(0x57, 0X7e); //write_data(0x00,); //
	LCD_WriteReg(0x58, 0X09); //write_data(0x00,); //
	LCD_WriteReg(0x59, 0X06); //write_data(0x00,); //
	LCD_WriteReg(0x5A, 0X06); //write_data(0x00,); //
	LCD_WriteReg(0x5B, 0X0d); //write_data(0x00,); //
	LCD_WriteReg(0x5C, 0X1F); //write_data(0x00,); //
	LCD_WriteReg(0x5D, 0XFF); //write_data(0x00,); //
	// Power Voltage Setting
	LCD_WriteReg(0x1B, 0X1A); //write_data(0x00);
	LCD_WriteReg(0x1A, 0X02); //write_data(0x00);
	LCD_WriteReg(0x24, 0X61); //write_data(0x00);
	LCD_WriteReg(0x25, 0X5C); //write_data(0x00);
	// Vcom offset
	// LCD_WriteReg(0x23,0x8D); // FLICKER ADJUST
	LCD_WriteReg(0x23, 0x62); //write_data(0x00,0X62);
	// Power ON Setting
	LCD_WriteReg(0x18, 0X36); //write_data(0x00); //RADJ 70Hz
	LCD_WriteReg(0x19, 0X01); //write_data(0x00,0X01); //OSC_EN=1
	LCD_WriteReg(0x1F, 0X88); //write_data(0x00,0X88); // GAS=1, VOMG=00, PON=0, DK=1, XDK=0, DVDH_TRI=0, STB=0
	delay_ms(5);
	LCD_WriteReg(0x1F, 0X80); //write_data(0x00,0X80); // GAS=1, VOMG=00, PON=0, DK=0, XDK=0, DVDH_TRI=0, STB=0
	delay_ms(5);
	LCD_WriteReg(0x1F, 0X90); //write_data(0x00,0X90); // GAS=1, VOMG=00, PON=1, DK=0, XDK=0, DVDH_TRI=0, STB=0
	delay_ms(5);
	LCD_WriteReg(0x1F, 0XD4); //write_data(0x00,0XD4); // GAS=1, VOMG=10, PON=1, DK=0, XDK=1, DDVDH_TRI=0, STB=0
	delay_ms(5);
	//262k/65k color selection
	LCD_WriteReg(0x17, 0X05); //write_data(0x00,0X05); //default 0x06 262k color // 0x05 65k color
	//SET PANEL
	LCD_WriteReg(0x36, 0X09); //write_data(0x00,0X09); //SS_P, GS_P,REV_P,BGR_P
	//Display ON Setting
	LCD_WriteReg(0x28, 0X38); //write_data(0x00,0X38); //GON=1, DTE=1, D=1000
	delay_ms(40);
	LCD_WriteReg(0x28, 0X3C); //write_data(0x00,0X3C); //GON=1, DTE=1, D=1100


	LCD_SetParam();//设置LCD参数	 
	LCD_LED=1;//点亮背光	 
	//LCD_Clear(WHITE);
}
  		  
/*************************************************
函数名：LCD_SetWindows
功能：设置lcd显示窗口，在此区域写点数据自动换行
入口参数：xy起点和终点
返回值：无
*************************************************/
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
{	
	LCD_WriteReg(0x0002,xStar>>8);
	LCD_WriteReg(0x0003,xStar);
	LCD_WriteReg(0x0004,xEnd>>8);
	LCD_WriteReg(0x0005,xEnd);
	LCD_WriteReg(0x0006,yStar>>8);
	LCD_WriteReg(0x0007,yStar);
	LCD_WriteReg(0x0008,yEnd>>8);
	LCD_WriteReg(0x0009,yEnd);
	LCD_WriteRAM_Prepare();	//开始写入GRAM	
}   

/*************************************************
函数名：LCD_SetCursor
功能：设置光标位置
入口参数：xy坐标
返回值：无
*************************************************/
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{	  	    			
	LCD_SetWindows(Xpos,Ypos,Xpos,Ypos);
} 

//设置LCD参数
//方便进行横竖屏模式切换
void LCD_SetParam(void)
{ 	
	lcddev.wramcmd=0x22;
#if USE_HORIZONTAL==1	//使用横屏	  
	lcddev.dir=1;//横屏
	lcddev.width=320;
	lcddev.height=240;
	lcddev.setxcmd=0x21;
	lcddev.setycmd=0x20;			
	LCD_WriteReg(0x0016,0x60);
	//LCD_WriteReg(0x36, 0X0F); //write_data(0x00,0X09); //SS_P, GS_P,REV_P,BGR_P
	//LCD_WriteReg(0x0060,0x2700);

#else//竖屏
	lcddev.dir=0;//竖屏				 	 		
	lcddev.width=240;
	lcddev.height=320;
	lcddev.setxcmd=0x20;
	lcddev.setycmd=0x21;	
	LCD_WriteReg(0x0016,0x00c0);
	//LCD_WriteReg(0x0060,0xA700);
#endif
}	


