#ifndef _LCD320240_H_
#define _LCD320240_H_

//#include "charcter.h"
#include "LCD_COLOR.h"
#include "font.h"

#define os_lcd_task_enter_critical 	os_task_enter_critical
#define os_lcd_task_exit_critical 	os_task_exit_critical
//#define LCD_Width 240
//#define LCD_Heigh 320  

static Lcd_Lib_Typedef *FontLib;

void Delay (u32 nCount)
{
	volatile int i;	 	
	for (i=0;i<nCount*1000;i++);
}

void LCD_PinInit(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//初始化数据总线端口
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = 0x00FF;   //初始化PA0-7 相对data8-data15
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOE, &GPIO_InitStructure);

 //初始化控制总线端口RD	-PC12,WR-PC11,RS-PC10,CS-PC13
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14|GPIO_Pin_15|GPIO_Pin_13;   //初始化
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  
   //初始化控制总线端口RST-PE6
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;   //初始化
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  //BACK LED
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;   //初始化
  GPIO_Init(GPIOD, &GPIO_InitStructure);
}
#define LCD_BACKLED_GPIO	GPIOD
#define LCD_BACKLED_PIN	4
void SetCS(u8 temp){if(temp){GPIOC->BSRR=GPIO_Pin_13;}else{GPIOC->BRR=GPIO_Pin_13;}}
void SetRS(u8 temp){if(temp){GPIOC->BSRR=GPIO_Pin_14;}else{GPIOC->BRR=GPIO_Pin_14;}}
void SetWR(u8 temp){if(temp){GPIOC->BSRR=GPIO_Pin_15;}else{GPIOC->BRR=GPIO_Pin_15;}}
void SetRD(u8 temp){if(temp){GPIOD->BSRR=GPIO_Pin_5;}else{GPIOD->BRR=GPIO_Pin_5;}}
void SetReset(u8 temp){if(temp){GPIOB->BSRR=GPIO_Pin_2;}else{GPIOB->BRR=GPIO_Pin_2;}}
void SetBackLed(u8 temp){if(temp){GPIOD->BSRR=GPIO_Pin_4;}else{GPIOD->BRR=GPIO_Pin_4;}}
//#####################################
void LCD_Write_Bus(u8 VH,u8 VL)
{
	u16 getdata,setdata;
	
	SetWR(0);
	GPIOE->BSRR=(VH & 0xFF)|(((~VH) & 0xFF)<<16);
	SetWR(1);
	
	SetWR(0);
	GPIOE->BSRR=(VL & 0xFF)|(((~VL) & 0xFF)<<16);
	SetWR(1);
}

void LCD_Write_Com(u8 VH,u8 VL)
{
SetRS(0);
LCD_Write_Bus(VH,VL);
}

void LCD_Write_Data(u8 VH,u8 VL)
{
SetRS(1);
LCD_Write_Bus(VH,VL);
}

void  LCD_WR_REG(u16 Command,u16 Data)
{
LCD_Write_Com(Command>>8,Command);
LCD_Write_Data(Data>>8,Data);
}
void LCD_Write_Bus8Bit(u8 V)//9341
{
	SetWR(0);
	GPIOE->BSRR=(V & 0xFF)|(((~V) & 0xFF)<<16);
	SetWR(1);
}
void LCD_Write_Com8Bit(u8 V)//9341
{
	SetRS(0);
	LCD_Write_Bus8Bit(V);
}
void LCD_Write_Data8Bit(u8 V)//9341
{
	SetRS(1);
	LCD_Write_Bus8Bit(V);
}
void LCD_Write_Com16Bit(u16 V)//9341
{
	SetRS(0);
	LCD_Write_Bus8Bit(V>>8);
	LCD_Write_Bus8Bit(V&0xff);
}
void LCD_Write_Data16Bit(u16 V)//9341
{
	SetRS(1);
	LCD_Write_Bus8Bit(V>>8);
	LCD_Write_Bus8Bit(V&0xff);
}
void LCD_Init(void)
{
SetReset(1);
Delay(10);
SetReset(0);
Delay(50);
SetReset(1);
SetCS(1);
SetRD(1);
SetWR(1);
Delay(50);

SetCS(0);
if(ReadLcdVersion()==LCD_ILI9325)
{
//************* Start Initial Sequence **********// 
LCD_Write_Com(0x00,0x01); LCD_Write_Data(0x01,0x00); // set SS and SM bit 
LCD_Write_Com(0x00,0x02); LCD_Write_Data(0x07,0x00); // set 1 line inversion 
LCD_Write_Com(0x00,0x03); LCD_Write_Data(0x10,0x30); // set GRAM write direction and BGR=1. 
LCD_Write_Com(0x00,0x04); LCD_Write_Data(0x00,0x00); // Resize register 
LCD_Write_Com(0x00,0x08); LCD_Write_Data(0x02,0x07); // set the back porch and front porch 
LCD_Write_Com(0x00,0x09); LCD_Write_Data(0x00,0x00); // set non-display area refresh cycle ISC[3:0] 
LCD_Write_Com(0x00,0x0A); LCD_Write_Data(0x00,0x00); // FMARK function 
LCD_Write_Com(0x00,0x0C); LCD_Write_Data(0x00,0x00); // RGB interface setting 
LCD_Write_Com(0x00,0x0D); LCD_Write_Data(0x00,0x00); // Frame marker Position 
LCD_Write_Com(0x00,0x0F); LCD_Write_Data(0x00,0x00); // RGB interface polarity 
//*************Power On sequence ****************// 
LCD_Write_Com(0x00,0x10); LCD_Write_Data(0x00,0x00); // SAP, BT[3:0], AP, DSTB, SLP, STB 
LCD_Write_Com(0x00,0x11); LCD_Write_Data(0x00,0x07); // DC1[2:0], DC0[2:0], VC[2:0] 
LCD_Write_Com(0x00,0x12); LCD_Write_Data(0x00,0x00); // VREG1OUT voltage 
LCD_Write_Com(0x00,0x13); LCD_Write_Data(0x00,0x00); // VDV[4:0] for VCOM amplitude 
LCD_Write_Com(0x00,0x07); LCD_Write_Data(0x00,0x01); 
LCD_Write_Com(0x00,0x07); LCD_Write_Data(0x00,0x20); 
Delay(50); // Dis-charge capacitor power voltage 
LCD_Write_Com(0x00,0x10); LCD_Write_Data(0x12,0x90); // 1490//SAP, BT[3:0], AP, DSTB, SLP, STB 
LCD_Write_Com(0x00,0x11); LCD_Write_Data(0x02,0x21); // DC1[2:0], DC0[2:0], VC[2:0] 
Delay(50);// Delay 50ms 
LCD_Write_Com(0x00,0x12); LCD_Write_Data(0x00,0x81); //001C// Internal reference voltage= Vci; 
Delay(50); // Delay 50ms 
LCD_Write_Com(0x00,0x13); LCD_Write_Data(0x15,0x00); //0x1000//1400   Set VDV[4:0] for VCOM amplitude  1A00 
LCD_Write_Com(0x00,0x29); LCD_Write_Data(0x00,0x0C); //0x0012 //001a  Set VCM[5:0] for VCOMH  //0x0025  0034 
LCD_Write_Com(0x00,0x2B); LCD_Write_Data(0x00,0x0D); // Set Frame Rate   000C 
Delay(50);// Delay 50ms 
LCD_Write_Com(0x00,0x20); LCD_Write_Data(0x00,0x00); // GRAM horizontal Address 
LCD_Write_Com(0x00,0x21); LCD_Write_Data(0x00,0x00); // GRAM Vertical Address 
// ----------- Adjust the Gamma Curve ----------// 
LCD_Write_Com(0x00,0x30); LCD_Write_Data(0x03,0x03); 
LCD_Write_Com(0x00,0x31); LCD_Write_Data(0x00,0x06); 
LCD_Write_Com(0x00,0x32); LCD_Write_Data(0x00,0x01); 
LCD_Write_Com(0x00,0x35); LCD_Write_Data(0x02,0x04); 
LCD_Write_Com(0x00,0x36); LCD_Write_Data(0x00,0x04);//0207 
LCD_Write_Com(0x00,0x37); LCD_Write_Data(0x04,0x07);//0306 
LCD_Write_Com(0x00,0x38); LCD_Write_Data(0x00,0x00);//0102 
LCD_Write_Com(0x00,0x39); LCD_Write_Data(0x04,0x04);//0707 
LCD_Write_Com(0x00,0x3C); LCD_Write_Data(0x04,0x02);//0702 
LCD_Write_Com(0x00,0x3D); LCD_Write_Data(0x00,0x04);//1604 

//------------------ Set GRAM area ---------------// 
LCD_Write_Com(0x00,0x50); LCD_Write_Data(0x00,0x00); // Horizontal GRAM Start Address 
LCD_Write_Com(0x00,0x51); LCD_Write_Data(0x00,0xEF); // Horizontal GRAM End Address 
LCD_Write_Com(0x00,0x52); LCD_Write_Data(0x00,0x00); // Vertical GRAM Start Address 
LCD_Write_Com(0x00,0x53); LCD_Write_Data(0x01,0x3F); // Vertical GRAM Start Address 
LCD_Write_Com(0x00,0x60); LCD_Write_Data(0xA7,0x00); // Gate Scan Line 
LCD_Write_Com(0x00,0x61); LCD_Write_Data(0x00,0x01); // NDL,VLE, REV 
LCD_Write_Com(0x00,0x6A); LCD_Write_Data(0x00,0x00); // set scrolling line 
//-------------- Partial Display Control ---------// 
LCD_Write_Com(0x00,0x80); LCD_Write_Data(0x00,0x00); 
LCD_Write_Com(0x00,0x81); LCD_Write_Data(0x00,0x00); 
LCD_Write_Com(0x00,0x82); LCD_Write_Data(0x00,0x00); 
LCD_Write_Com(0x00,0x83); LCD_Write_Data(0x00,0x00); 
LCD_Write_Com(0x00,0x84); LCD_Write_Data(0x00,0x00); 
LCD_Write_Com(0x00,0x85); LCD_Write_Data(0x00,0x00); 
//-------------- Panel Control -------------------// 
LCD_Write_Com(0x00,0x90); LCD_Write_Data(0x00,0x10); 
LCD_Write_Com(0x00,0x92); LCD_Write_Data(0x06,0x00); 
LCD_Write_Com(0x00,0x07); LCD_Write_Data(0x01,0x33); // 262K color and display ON 
}
else//7789
{
	//--------------------------------ST7789S Frame rate setting----------------------------------//
	LCD_Write_Com8Bit(0xb2);
	LCD_Write_Data8Bit(0x0c);
	LCD_Write_Data8Bit(0x0c);
	LCD_Write_Data8Bit(0x00);
	LCD_Write_Data8Bit(0x33);
	LCD_Write_Data8Bit(0x33);

	LCD_Write_Com8Bit(0xb7);
	LCD_Write_Data8Bit(0x35);


	LCD_Write_Com8Bit  (0x36);  //显示方向  Memory Access Control
	LCD_Write_Data8Bit (0x00);	//

	LCD_Write_Com8Bit(0x3A);
	LCD_Write_Data8Bit(0x55);//65K RGB color 16BIT
	//---------------------------------ST7789S Power setting--------------------------------------//
	LCD_Write_Com8Bit(0xbb);
	LCD_Write_Data8Bit(0x30);//vcom

	LCD_Write_Com8Bit(0xc3);
	LCD_Write_Data8Bit(0x20);//17调深浅


	LCD_Write_Com8Bit(0xc4);

	LCD_Write_Data8Bit(0x1E);//25

	LCD_Write_Com8Bit(0xc6);
	LCD_Write_Data8Bit(0x04);//82HZ

	LCD_Write_Com8Bit(0xd0);
	LCD_Write_Data8Bit(0xa4);
	LCD_Write_Data8Bit(0xa2);
	//--------------------------------ST7789S gamma setting---------------------------------------//
	LCD_Write_Com8Bit(0xe0);
	LCD_Write_Data8Bit(0xf0);
	LCD_Write_Data8Bit(0x00);
	LCD_Write_Data8Bit(0x0a);
	LCD_Write_Data8Bit(0x10);
	LCD_Write_Data8Bit(0x12);
	LCD_Write_Data8Bit(0x1b);
	LCD_Write_Data8Bit(0x39);
	LCD_Write_Data8Bit(0x44);
	LCD_Write_Data8Bit(0x47);
	LCD_Write_Data8Bit(0x28);
	LCD_Write_Data8Bit(0x12);
	LCD_Write_Data8Bit(0x10);
	LCD_Write_Data8Bit(0x16);
	LCD_Write_Data8Bit(0x1b);

	LCD_Write_Com8Bit(0xe1);
	LCD_Write_Data8Bit(0xf0);
	LCD_Write_Data8Bit(0x00);
	LCD_Write_Data8Bit(0x0a);
	LCD_Write_Data8Bit(0x10);
	LCD_Write_Data8Bit(0x11);
	LCD_Write_Data8Bit(0x1a);
	LCD_Write_Data8Bit(0x3b);
	LCD_Write_Data8Bit(0x34);
	LCD_Write_Data8Bit(0x4e);
	LCD_Write_Data8Bit(0x3a);
	LCD_Write_Data8Bit(0x17);
	LCD_Write_Data8Bit(0x16);
	LCD_Write_Data8Bit(0x21);
	LCD_Write_Data8Bit(0x22);

	LCD_Write_Com8Bit(0x3a);
	LCD_Write_Data8Bit(0x55); //18 RGB ,55-16BIT RGB

	//************************
	LCD_Write_Com8Bit(0x11);
	Delay(120);      //Delay 120ms

	LCD_Write_Com8Bit(0x29); //display on
	LCD_Write_Com8Bit(0x2c);
}
SetCS(1); //关闭片选使能
}

void Address_set(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2) 
{ 
	if(ReadLcdVersion()==LCD_ILI9325)
	{
		LCD_Write_Com(0x00, 0x20); LCD_Write_Data(x1 >> 8, x1); //设置X坐标位置 
		LCD_Write_Com(0x00, 0x21); LCD_Write_Data(y1 >> 8, y1); //设置Y坐标位置 
		LCD_Write_Com(0x00, 0x50); LCD_Write_Data(x1 >> 8, x1); //开始X 
		LCD_Write_Com(0x00, 0x52); LCD_Write_Data(y1 >> 8, y1); //开始Y 
		LCD_Write_Com(0x00, 0x51); LCD_Write_Data(x2 >> 8, x2); //结束X 
		LCD_Write_Com(0x00, 0x53); LCD_Write_Data(y2 >> 8, y2); //结束Y 
		LCD_Write_Com(0x00, 0x22); 
	}
	else
	{
		LCD_Write_Com8Bit  (0x2A);
		LCD_Write_Data16Bit(x1);//开始X
		LCD_Write_Data16Bit(x2);//结束X
		LCD_Write_Com8Bit  (0x2B);
		LCD_Write_Data16Bit(y1);//开始Y
		LCD_Write_Data16Bit(y2);//结束Y
		LCD_Write_Com8Bit  (0x2C);
	}
} 

void LCD_Pant(u16 color) 
{ 
	int i, j;
	os_task_enter_critical();
	SetCS(0); //打开片选使能
	Address_set(0,0,LCD_Width-1,LCD_Heigh-1);
	for(i = 0; i < LCD_Heigh; i++)
	{ 
		for (j = 0; j < LCD_Width; j++)
		{
			LCD_Write_Data(color>>8, color);
		}
	} 
	SetCS(1); //关闭片选使能
	os_lcd_task_exit_critical();
} 

void LCD_DrawPoint(s16 x,s16 y,u16 color)
{
	os_task_enter_critical();
	SetCS(0); //打开片选使能
	Address_set(x,y,x,y);
	LCD_Write_Data(color>>8, color);
	SetCS(1); //关闭片选使能
	os_lcd_task_exit_critical();
}
void LCD_drawpointgrma(s16 x,s16 y,u16 color)
{
	if(x<0||y<0||x>=LCD_Width||y>=LCD_Heigh)return;
	Address_set(x,y,x,y);
	LCD_Write_Data(color>>8, color);
}
//图标大小为64*64
void LCD_DrawPicture(s16 x,s16 y,u8* pBuf,u16 F_Color,u16 B_Color)
{
	u8 i,j,k,m_var0;
	os_task_enter_critical();
	SetCS(0); //打开片选使能
	Address_set(x,y,x+63,y+63);
	for(i=0;i<64;i++)
	{
    for(j=0;j<8;j++)
    {
    	m_var0=*(pBuf+8*i+j);
    	for(k=0;k<8;k++)
	    {
    		if((m_var0&(0x01<<k))!=0)
    		{
    			LCD_Write_Data(F_Color>>8, F_Color);
    		}
    		else
    		{
		    	LCD_Write_Data(B_Color>>8, B_Color); 
    		}
	    }
    }
	}
	SetCS(1); //关闭片选使能
	os_lcd_task_exit_critical();
}
void SetLCDFontLib(Lcd_Lib_Typedef *mFontLib)//设置字库
{
	os_task_enter_critical();//临界区处理,禁止任务调度破坏共享资源
	FontLib=mFontLib;
	os_lcd_task_exit_critical();
}
u8 LCD_Font(s16 x,s16 y,u8 *ch,u16 ch_color,u16 bg_color,u8 transparent,Lcd_Lib_Typedef *mFontLib)
{
	s16 i,j,xi,yi,x0,y0;
	s32 c;
	u8 m;
	vu32 saddr;
	u16 w=mFontLib->width,h=mFontLib->height;
	u16 dotsize;//字体分辨率必须为8的整数倍
	////Printf("Lib=%08X,type=%X\r\n",mFontLib,mFontLib->type);
	//读取字库中指针偏移量
	switch(mFontLib->type)
	{
		case FONT_TYPE_ASCII://ascii
		{
			c=*ch-32;
		}break;
		default://中文
		{	//字符集偏移量地址＝(H-0xB0)*188+(L-0xA1)*2
			//其中H是汉字的高位，区码
			//其中L是汉字的低位，位码
			//字库的寻址地址＝(字符集偏移量地址/2)*单字模大小字节数＝[(H-0xB0)*94+(L-0xA1)]*单字模大小字节数
			c=(*ch-0xB0)*94+(*(ch+1)-0XA1);
		}break;
	}
	if(c>=mFontLib->fsize||c<0)return 0;//字库中不包含该字符则直接返回

	saddr=mFontLib->startaddress+c*mFontLib->fsbyte;//起始地址
	dotsize=w*h;//字体分辨率

	xi=(s16)(x+w-1);yi=(s16)(y+h-1);
	//print("xi=%d,yi=%d\r\n",xi,yi);
	if(x>=LCD_Width||y>=LCD_Heigh||xi<0||yi<0)return 1;//超出显示边界
	if(x<0){x0=0;}else x0=x;
	if(y<0){y0=0;}else y0=y;
	os_lcd_task_enter_critical();//临界区处理,禁止任务调度破坏共享资源
	FontLib=mFontLib;//保存当前字库
	SetCS(0); //打开片选使能
	if(transparent!=1)
	{
		if(xi>=LCD_Width)xi=LCD_Width-1;if(yi>=LCD_Heigh)yi=LCD_Heigh-1;
		//Address_set(x,y,(x+w-1),(y+h-1));
		Address_set(x0,y0,xi,yi);
	}
	if(mFontLib->fonttype==LCD_TYPED_CN_O||mFontLib->fonttype==LCD_TYPED_ASCII_O)
	{
		//Printf("设置读地址=0x%X\r\n",saddr);
		sFlash_SetReadStartAddr(saddr);//设FLASH读起始地址
	}
  for(i=0;i<dotsize;i)
	{//获取1byte
  	if(mFontLib->fonttype==LCD_TYPED_CN_O||mFontLib->fonttype==LCD_TYPED_ASCII_O)//使用外部字库
  	{
  		m=sFlash_ReadByte();//读取1Byte数据
  		//Printf("%02X ",m);
  	}
		else //if(mFontLib->fonttype==LCD_TYPED_CN_I||mFontLib->fonttype==LCD_TYPED_ASCII_I)//使用内部字库情况下
		{
  		m=*(vu8 *)(saddr+(i>>3));//i/8
		}
		for(j=0;j<8;j++,i++) 
	 	{
			xi=(s16)((s16)x+(s16)i%w);yi=(s16)((s16)y+(s16)i/w);
			if(xi>=0&&yi>=0&&xi<LCD_Width&&yi<LCD_Heigh)
			{
				switch(transparent)
				{
					case 1://透明显示
					{
						//if(m&0x01)LCD_drawpointgrma(xi,yi, ch_color);//LCD_DrawPoint((x+i%w),(y+i/w), ch_color);
						if(m&(1<<j))LCD_drawpointgrma(xi,yi, ch_color);//LCD_DrawPoint(xi,yi, ch_color);
					}break;
					default:
					{
						//if(m&0x01)LCD_Write_Data(ch_color>>8, ch_color);
						if(m&(1<<j))LCD_Write_Data(ch_color>>8, ch_color);
						else LCD_Write_Data(bg_color>>8, bg_color);
					}break;
				}
			}
			//m>>=1;//指向下一位
		}
	}
  if(mFontLib->fonttype==LCD_TYPED_CN_O||FontLib->fonttype==LCD_TYPED_ASCII_O)
  {
  	//Printf("\r\n等待读完成\r\n");
  	sFlash_WaitReadFinsh();
  	//Printf(" 完成\r\n");
  }
	
	SetCS(1); //打开片选使能
	os_lcd_task_exit_critical();//开启任务调度
	return 1;
}
u8 LCD_DisplayFont(s16 x,s16 y,u8 *ch,u16 ch_color,u16 bg_color,u8 transparent,u8 type)
{
	u8 state;
	Lcd_Lib_Typedef *mFontLib;

	os_task_enter_critical();//临界区处理,禁止任务调度破坏共享资源
  mFontLib=GetLcdFont(type);//读取字库
  os_lcd_task_exit_critical();//开启任务调度

	state=LCD_Font(x,y,ch,ch_color,bg_color,transparent,(Lcd_Lib_Typedef *)mFontLib);
	//os_lcd_task_exit_critical();//开启任务调度
	return state;
}
void LCD_en(s16 x,s16 y,u8 ch,u16 ch_color,u16 bg_color,u8 transparent)
{
	LCD_DisplayFont( x, y,&ch, ch_color, bg_color, transparent,GetAsciiFontType());
}

void LCD_DisplayString(s16 x,s16 y,u8* ch,u16 ch_color,u16 bg_color,u8 transparent)
{
	u8 type=0,i;
	Lcd_Lib_Typedef *mFontLib;//临时缓存，保存当前字库
	while((*ch)!='\0')
	{//判断字符类型
		if(*ch<0x80){type=GetAsciiFontType();}//ascii
		else {type=GetChineseFontType();}//中文

		//读取当前字库
		os_task_enter_critical();//临界区处理,禁止任务调度破坏共享资源
	  mFontLib=GetLcdFont(type);//读取字库
	  os_lcd_task_exit_critical();//开启任务调度

		//回车换行符处理
		if(*ch=='\n'){y+=mFontLib->height;ch++;continue;}//0x0A换行 Line Feed
		else if(*ch=='\r'){x=0;ch++;continue;}           //0X0D回车 Carriage Return
		if(LCD_DisplayFont( x, y, ch, ch_color, bg_color, transparent,type)==0)//判断要显示的字符是否在中文字库里面
		{//在字库列表中找不到相应字库,则显示为空格
			for(i=0;i<mFontLib->charbyte;i++)
			{
				LCD_en( x, y,' ', ch_color, bg_color, transparent);
			}
		}
		//指向下一个字符
		ch+=mFontLib->charbyte;
		x+=mFontLib->width;
	}
}
void LCD_String(s16 x,s16 y,u8* ch,u16 ch_color,u16 bg_color)
{
	LCD_DisplayString(x,y,ch,ch_color,bg_color,0);
}
//字体当前分辨率
u16 GetFontLibWidth(void){return FontLib->width;}
u16 GetFontLibHeight(void){return FontLib->height;}
void SetNumFontType(void){FontLib=GetLcdFont(GetAsciiFontType());}//读取数字字库
u32 GetLCDFontLib(void){	return FontLib;}
u16 GetLCDFontType(void){return FontLib->type;}
void LCD_DrawRectangle(u16 x1,u16 y1,u16 x2,u16 y2,u16 color)
{
	int i, j;
	os_task_enter_critical();//临界区处理,禁止任务调度破坏共享资源
	SetCS(0); //打开片选使能
	Address_set(x1,y1,x2,y2);
	for(i = x1; i <= x2; i++)
	{
		for (j =y1; j <= y2; j++)
		{
			LCD_Write_Data(color>>8, color);
		}
	}
	SetCS(1); //关闭片选使能
	os_lcd_task_exit_critical();//开启任务调度
}

void LCD_DispChar(s16 x,s16 y,u8 *ch,u16 F_Color,u16 B_Color)
{
	u8 i,j,k,m_var0;
	os_task_enter_critical();//临界区处理,禁止任务调度破坏共享资源
	SetCS(0); //打开片选使能
	Address_set(x,y,x+31,y+31);
	for(i=0;i<32;i++)
	{
		for(j=0;j<4;j++)
		{
			m_var0=*(ch+4*i+j);
			for(k=0;k<8;k++)
			{
				if((m_var0&(0x01<<k))!=0)
				{
					LCD_Write_Data(F_Color>>8, F_Color);
				}
				else
				{
					LCD_Write_Data(B_Color>>8, B_Color);
				}
			}
		}
	}
	SetCS(1); //关闭片选使能
	os_lcd_task_exit_critical();//开启任务调度
}

//*******************************************************************************
// Function Name  : LCD_DisplayNumU32
// Description    : 显示函数无符号型
// Input          : x,y:数字起始坐标;
//					        num:显示的数字
//					        ch_color:字体颜色
//					        bg_color:背景颜色
//					        size:显示的数字个数;
//					             十进制数:size低四位BIT0-BIT3:1~8显示数据位;BIT7:0x80显示符号，0x00不显示符号，BIT15:字体类型,1为默认系统类型,0强制转换为ASCII8X16,BIT14:1保存前面的0,BIT13:1强制保留符号不管正负
//					             十六进制数:size低四位BIT0-BIT3:1~8显示数据位;BIT6:0X40显示16进制数,0X00显示十进制
// Output         : None
// Return         : None
// Author		      : LXW 2018/07/04
//*******************************************************************************
void LCD_DisplayNumU32(s16 x,s16 y,u32 num,u16 ch_color,u16 bg_color,u16 size)//-0X7FFF FFFF ~ 0X7FFF FFFF
{
	u8 temp[18];//-2147483647~2147483647 10位
	s8 i=0,nn;
	u8 NumSign=0;	//0就是正，1就是负
	u8 ii=0,flag=0,ns=size&0x80, hex=size&0x40, n=10,t=size>>15,tt=(size>>14)&0x01,st=(size>>13)&0x01;
	u32 m=num;
	u16 type=GetAsciiFontType();//保存字体类型
	Lcd_Lib_Typedef *mFontLib;//临时缓存，保存当前字库
	//读取当前字库
	os_task_enter_critical();//临界区处理,禁止任务调度破坏共享资源
	if(t==0)SetAsciiFontType(0);//强制转换显示类型为ascii8X16
  mFontLib=GetLcdFont(GetAsciiFontType());//读取字库
  os_lcd_task_exit_critical();//开启任务调度

	size&=0x0f;
	ii=size;
	if(hex)//十六进制
	{
		n=16;
		num=(u32)num;
		if(ns)NumSign=1;//显示0x
	}
	else //if(hex==0x00)//十进制
	{
		if(num<0)
		{
			num=-num;
			NumSign= 1;//负数显示符号
		}
		if(!ns){ii=size-1;NumSign=0;}
	}
	for(i=0;i<size;i++)
	{
		nn=num%n;
		if(nn<10)temp[i]='0'+nn;
		else if(nn>9)temp[i]='A'+nn-10;
		num/=n;
	}
	if(hex)
	{
		ii=size-1;
		if(NumSign)
		{
			ii+=2;
			temp[ii]='0';
			temp[ii-1]='x';
		}
		else	
		{
			temp[size]=' ';
		}
	}
	else 
	{
		temp[size]=' ';
	}
	for(i=size;i>-1;i--)
	{
		if((temp[i-1]!=48)&&(flag==0))
		{
			if(hex==0x00)
			{
				if(NumSign==1&&m!=0)	temp[i]='-';
				else
				{
					if(st&&i==0)temp[1]='-';
				}
			}
			flag=1;
		}
		else
		{
			if((flag==0)&&(i>1))
			{
				if(hex){if(NumSign!=1)	{if(tt==0)temp[i-1]=' ';}}
				else {if(tt==0)temp[i-1]=' ';}
			}
		}
	}
	if(temp[0]==48){temp[0]='0';}
	for(i=ii;i>-1;i--)
	{
		LCD_en(x,y,temp[i],ch_color,bg_color,0);
		x+=mFontLib->width;
	}
	os_task_enter_critical();//临界区处理,禁止任务调度破坏共享资源
	if(t==0)SetAsciiFontType(type);//
	os_lcd_task_exit_critical();//开启任务调度
}



//*******************************************************************************
// Function Name  : LCD_DisplayNum
// Description    : 数字显示函数
// Input          : x,y:数字起始坐标;
//					        num:显示的数字
//					        ch_color:字体颜色
//					        bg_color:背景颜色
//					        size:显示的数字个数;
//					             十进制数:size低四位BIT0-BIT3:1~8显示数据位;BIT7:0x80显示符号，0x00不显示符号，BIT15:字体类型,1为默认系统类型,0强制转换为ASCII8X16,BIT14:1保存前面的0,BIT13:1强制保留符号不管正负
//					             十六进制数:size低四位BIT0-BIT3:1~8显示数据位;BIT6:0X40显示16进制数,0X00显示十进制
// Output         : None
// Return         : None
// Author		      : CZQ 2015/07/02
//*******************************************************************************
void LCD_DisplayNum(s16 x,s16 y,s32 num,u16 ch_color,u16 bg_color,u16 size)//-0X7FFF FFFF ~ 0X7FFF FFFF
{
	u8 temp[18];//-2147483647~2147483647 10位
	s8 i=0,nn;
	u8 NumSign=0;	//0就是正，1就是负
	u8 ii=0,flag=0,ns=size&0x80, hex=size&0x40, n=10,t=size>>15,tt=(size>>14)&0x01,st=(size>>13)&0x01;
	s32 m=num;
	u16 type=GetAsciiFontType();//保存字体类型
	Lcd_Lib_Typedef *mFontLib;//临时缓存，保存当前字库
	//读取当前字库
	os_task_enter_critical();//临界区处理,禁止任务调度破坏共享资源
	if(t==0)SetAsciiFontType(0);//强制转换显示类型为ascii8X16
  mFontLib=GetLcdFont(GetAsciiFontType());//读取字库
  os_lcd_task_exit_critical();//开启任务调度

	size&=0x0f;
	ii=size;
	if(hex)//十六进制
	{
		n=16;
		num=(u32)num;
		if(ns)NumSign=1;//显示0x
	}
	else //if(hex==0x00)//十进制
	{
		if(num<0)
		{
			num=-num;
			NumSign= 1;//负数显示符号
		}
		if(!ns){ii=size-1;NumSign=0;}
	}
	for(i=0;i<size;i++)
	{
		nn=num%n;
		if(nn<10)temp[i]='0'+nn;
		else if(nn>9)temp[i]='A'+nn-10;
		num/=n;
	}
	if(hex)
	{
		ii=size-1;
		if(NumSign)
		{
			ii+=2;
			temp[ii]='0';
			temp[ii-1]='x';
		}
		else	
		{
			temp[size]=' ';
		}
	}
	else 
	{
		temp[size]=' ';
	}
	for(i=size;i>-1;i--)
	{
		if((temp[i-1]!=48)&&(flag==0))
		{
			if(hex==0x00)
			{
				if(NumSign==1&&m!=0)	temp[i]='-';
				else
				{
					if(st&&i==0)temp[1]='-';
				}
			}
			flag=1;
		}
		else
		{
			if((flag==0)&&(i>1))
			{
				if(hex){if(NumSign!=1)	{if(tt==0)temp[i-1]=' ';}}
				else {if(tt==0)temp[i-1]=' ';}
			}
		}
	}
	if(temp[0]==48){temp[0]='0';}
	for(i=ii;i>-1;i--)
	{
		LCD_en(x,y,temp[i],ch_color,bg_color,0);
		x+=mFontLib->width;
	}
	os_task_enter_critical();//临界区处理,禁止任务调度破坏共享资源
	if(t==0)SetAsciiFontType(type);//
	os_lcd_task_exit_critical();//开启任务调度
}
//显示浮点型数据
void LCD_DisplayFloatNum(s16 x,s16 y,double num,u16 ch_color,u16 bg_color,u16 size)//size 高8位为显示整数位数,低八位为小数点位数
{
	s32 i_num,d_num;
	u16 i_size=(size>>8)&0x0f,d_size=size&0x0f;
	double mm;
	u16 w=GetFontLibWidth();
	u8 flag=0,i;
	if(num<0)flag=1;
	i_num=(s32)num;
	num-=i_num;
	if(flag)num-=0.000000005;//四舍五入
	else num+=0.000000005;//四舍五入
	mm=num;
	for(i=0;i<d_size;i++)mm*=10;
	d_num=(s32)mm;
	LCD_DisplayNum(x,y,(s32)i_num,ch_color,bg_color,0x8080|i_size|(flag<<13));//整数
	x+=(w*(i_size+1));
	LCD_en(x,y,'.',ch_color,bg_color,0);
	x+=w;
	LCD_DisplayNum(x,y,(u32)d_num,ch_color,bg_color,0xC000|d_size);//小数//*/
}
void LCD_3g(s16 x,s16 y,u32 num,u16 ch_color,u16 bg_color)
{
 u8 temp[3],i=0;
 	if(num>32767)
	{
	num	=	65536-num;
	LCD_en(x,y,'-',ch_color,bg_color,0);
	}
	else
	{
	LCD_en(x,y,' ',ch_color,bg_color,0);
	}
   for(i=0;i<3;i++)
   	{
   	temp[i]=num%10+48;
	num/=10;
	}
  LCD_en((x+FontLib->width  ),y,temp[2],ch_color,bg_color, 0);
	LCD_en((x+FontLib->width*2),y,temp[1],ch_color,bg_color, 0);
	LCD_en((x+FontLib->width*3),y,temp[0],ch_color,bg_color, 0);

}
//2147483647
//4294967296
void LCD_5g(s16 x,s16 y,u32 num,u16 ch_color,u16 bg_color,u8 transparent)
{
 u8 temp[5],i=0;
 	if(num>2147483647)
	{
	num	=	4294967296-num;
	LCD_en(x,y,'-',ch_color,bg_color,transparent);
	}
	else
	{
	LCD_en(x,y,' ',ch_color,bg_color,transparent);
	}
   for(i=0;i<5;i++)
   	{
   	temp[i]=num%10+48;
	num/=10;
	}
  LCD_en((x+FontLib->width  ),y,temp[4],ch_color,bg_color, transparent);
	LCD_en((x+FontLib->width*2),y,temp[3],ch_color,bg_color, transparent);
	LCD_en((x+FontLib->width*3),y,temp[2],ch_color,bg_color, transparent);
	LCD_en((x+FontLib->width*4),y,temp[1],ch_color,bg_color, transparent);
	LCD_en((x+FontLib->width*5),y,temp[0],ch_color,bg_color, transparent);
}

void LCD_8g(s16 x,s16 y,u32 num,u16 ch_color,u16 bg_color,u8 transparent)
{
 	u8 temp[9],i=0,flag=0;
	u8 NumSign=0;	//0就是正，1就是负
 	if(num>2147483647)
	{
	num	=	4294967296-num;
	NumSign	=	1;
	}

   	for(i=0;i<8;i++)
   	{
   	temp[i]=num%10+48;
	num/=10;
	}
	
	temp[8]=' ';
	for(i=8;i>0;i--)
	{
		if((temp[i-1]!=48)&&(flag==0))
		{
		if(NumSign==1)temp[i]='-';
		flag=1;
		}
		else if((flag==0)&&(i>1))
		{
		temp[i-1]=' ';
		}
		else if(temp[0]==48)
		{
		temp[0]='0';
		}
	}
	LCD_en(x,y,temp[8],ch_color,bg_color, transparent);
  LCD_en((x+FontLib->width  ),y,temp[7],ch_color,bg_color, transparent);
	LCD_en((x+FontLib->width*2),y,temp[6],ch_color,bg_color, transparent);
	LCD_en((x+FontLib->width*3),y,temp[5],ch_color,bg_color, transparent);
	LCD_en((x+FontLib->width*4),y,temp[4],ch_color,bg_color, transparent);
	LCD_en((x+FontLib->width*5),y,temp[3],ch_color,bg_color, transparent);
	LCD_en((x+FontLib->width*6),y,temp[2],ch_color,bg_color, transparent);
	LCD_en((x+FontLib->width*7),y,temp[1],ch_color,bg_color, transparent);
	LCD_en((x+FontLib->width*8),y,temp[0],ch_color,bg_color, transparent);
	
}


void LCD_4bit(s16 x,s16 y,u16 num,u16 ch_color,u16 bg_color,u8 transparent)
{
 u8 temp[4],i=0;
 
   for(i=0;i<5;i++)
   	{
   	temp[i]=num%10+48;
	num/=10;
	}


  for(i=3;i>0;i--)
   	{
   	if(temp[i]==48)temp[i]=32;//32是空格
   	else
   	{break;}
   	}

	  
  LCD_en(x,y,temp[3],ch_color,bg_color,transparent);
	LCD_en((x+FontLib->width),y,temp[2],ch_color,bg_color,transparent);
	LCD_en((x+FontLib->width*2),y,temp[1],ch_color,bg_color,transparent);
	LCD_en((x+FontLib->width*3),y,temp[0],ch_color,bg_color,transparent);
}

void LCD_5bit(s16 x,s16 y,u16 num,u16 ch_color,u16 bg_color)
{
 u8 temp[5],i=0;
 
   for(i=0;i<5;i++)
   	{
   	temp[i]=num%10+48;
	num/=10;
	}
  LCD_en(x,y,temp[4],ch_color,bg_color,0);
	LCD_en((x+FontLib->width),y,temp[3],ch_color,bg_color,0);
	LCD_en((x+FontLib->width*2),y,temp[2],ch_color,bg_color,0);
	LCD_en((x+FontLib->width*3),y,temp[1],ch_color,bg_color,0);
	LCD_en((x+FontLib->width*4),y,temp[0],ch_color,bg_color,0);
}

u8 g_RollLine=0;
u8 g_RollRow=0;//g_RollLine是行，g_RollRow是列
u8 g_FlashState=0;

void LCD_LineBreak(void)
{

	//行
	g_RollLine++;
	if(g_RollLine>10)
	{
	g_RollLine=0;
	g_FlashState=1;
	}
	//列
	g_RollRow=0;
	return 1;
}


void LCD_RollString(u8* ch,u16 ch_color,u16 bg_color,u8 linebreak,u8 transparent)
{
    u8 x=0;
	  if(g_FlashState==1){LCD_Pant(bg_color);g_FlashState=0;}
    while((*ch)!='\0')
    	{
    	  LCD_en(g_RollRow,g_RollLine*16+1,*ch,ch_color,bg_color,transparent);
	      ch++;
	      g_RollRow+=FontLib->width*2;
    	}
	if(linebreak==1)
		{
		LCD_LineBreak();
		}

}

void LCD_Roll5bit(u16 num,u16 ch_color,u16 bg_color,u8 linebreak,u8 transparent)
{
 u8 temp[5],i=0;
   if(g_FlashState==1){LCD_Pant(bg_color);g_FlashState=0;}
   for(i=0;i<5;i++)
   	{
   	temp[i]=num%10+48;
	num/=10;
	}
   for(i=0;i<5;i++)
   	{
   	LCD_en(g_RollRow,g_RollLine*16+1,temp[4-i],ch_color,bg_color,transparent);
	g_RollRow+=FontLib->width*2;
   	}
   if(linebreak==1)
   	{
   	LCD_LineBreak();
   	}
}

void LCD_cn(s16 x,s16 y,u8* pic,u16 ch_color,u16 bg_color,u8 transparent)
{
 	u8 i,j,var0,k,z=0;
	
	SetCS(0); //打开片选使能 
	for(i=0;i<32;i++)
	{
	k=i;
      	var0=*(pic+i);
	if(i>=16){z=8;k-=16;}
	for(j=0;j<8;j++)
	 	{
		if((var0&(0x01<<j))!=0){LCD_DrawPoint(x+j+z,y+k, ch_color);}
		else{if(transparent !=1){LCD_DrawPoint(x+j+z,y+k, bg_color);}}//transparent为1，透明
		}
	}
	SetCS(1); //关闭片选使能 
}
#endif

#ifdef _GETCHOICEBOX_
 #ifndef ____CHARACTER_EXT
 #define ____CHARACTER_EXT
 #include "charcter.h"
void LCD_Display4Chioce(void)
{
	LCD_DrawRectangle(27,65,96,134,YELLOW);
	LCD_DrawRectangle(27,176,96,245,YELLOW);
	LCD_DrawRectangle(143,176,212,245,YELLOW);
	LCD_DrawRectangle(143,65,212,134,YELLOW);
	//
	LCD_DispChar(46,84,Char_A,BLACK,YELLOW);
	LCD_DispChar(162,84,Char_B,BLACK,YELLOW);
	LCD_DispChar(46,195,Char_C,BLACK,YELLOW);
	LCD_DispChar(162,195,Char_D,BLACK,YELLOW);
}
 #endif
#endif
#ifdef _SETLCDLINE_
#ifndef __LCD_LINE_EXISTS_
#define __LCD_LINE_EXISTS_
//交换整数a、b的值
void Swap_Int(int *a,int *b)
{
	*a^=*b;	*b^=*a;	*a^=*b;
}
void LCD_DrawLine( int x1, int y1, int x2, int y2, u16 color,u8 size)
{
  int x,y;
  if(size)size-=1;
  int dx = abs(x2 - x1),
       dy = abs(y2 - y1),
       yy = 0;
  if(dx < dy)
  {
    yy = 1;
    Swap_Int(&x1, &y1);    Swap_Int(&x2, &y2);    Swap_Int(&dx, &dy);
  }
  int ix = (x2 - x1) > 0 ? 1 : -1, iy = (y2 - y1) > 0 ? 1 : -1,
       cx = x1, cy = y1, n2dy = dy * 2, n2dydx = (dy - dx) * 2, d = dy * 2 - dx;
  while(cx != x2)
	{
  	if(d < 0) { d += n2dy;  }
   	else
   	{
   		cy += iy;	d += n2dydx;
   	}
   	if(yy)	{x=cy;y=cx;	}//如果直线与 x 轴的夹角大于45度
   	else {x=cx;y=cy;}//如果直线与 x 轴的夹角小于45度
   	//LCD_DrawPoint(x, y, color);
   	LCD_DrawRectangle(x, y, x+size, y+size, color);//7(x,-y)象限4
   	cx += ix;
	}
}
//角度转弧度 π/180×角度
//弧度变角度 180/π×弧度 
//y = kx + b
//b=y1-kx1
//y2-y1=k*(x2-x1)->y2=y1+k*(x2-x1)=k*x2+b->
//k=tanA=(y2-y1)/(x2-x1).
void LCD_Line( int x1, int y1, int angle, int lenght, u16 color,u8 size)
{
	float a;int x2,y2,x3,y3;
	angle%=360;
	switch(angle)
	{
		case 0:			y2=y1;x2=x1+lenght;		break;		
		case 180:		y2=y1;x2=x1-lenght;		break;
		case 90:			y2=y1-lenght;x2=x1;		break;
		case 270:		y2=y1+lenght;x2=x1;		break;
		default:
		angle=360-angle;
		a=angle*3.14159265/180;//转换成弧度
		y2=y1+lenght*(sin(a)*1000)/1000;x2=x1+lenght*(cos(a)*1000)/1000;
		break;
	}
	if(x2<0)x2=0;if(y2<0)y2=0;
	if(x2>=240)x2=240;if(y2>=320)y2=320;
	LCD_DrawLine(x1, y1,x2,y2,color,size);
}
#endif//__LCD_LINE_EXISTS_
#endif//_SETLCDLINE_

#ifdef _SETDISPLAYPICTURE_
#ifndef ___SETDISPLAYPICTURE_EXISTS_
#define ___SETDISPLAYPICTURE_EXISTS_
#include"diskio.h"
#include "ff.h"
#include "tjpgd.h"
INT  UI_Display_Jpeg(FIL* f_Jpeg,//指向JPEG图片文件的指针
		                      const char* filename,//JPEG图片文件的名称
		                      UINT xstart,UINT ystart,
		                      BYTE scale,//jpeg图像缩放比例0-3 : 1,1/2,1/4,1/8
		                      void* pool,//指向本次解压工作区的指针(4字节对齐)
		                      UINT sz_pool);//解压工作区的大小
INT  UI_Display_Bmp (FIL* f_Bmp,//指向JPEG图片文件的指针
													const char* fn,	/* File to open */
													UINT xstart,UINT ystart,
													BYTE scale,//jpeg图像缩放比例0-3 : 1,1/2,1/4,1/8
													void *work,		/* Pointer to the working buffer (must be 4-byte aligned) */
													UINT sz_work);	/* Size of the working buffer (must be power of 2) */
int Call_DisplayPicture(void)
{
	if(ReadDisplayPictureFlag()==0)return -1;//等待一张图片显示完毕
	os_lcd_task_enter_critical();//os_port_enter_critical();//显示过程中要禁止其它任务调度
	s16 res;
	BYTE ImageBuffer[3100] __attribute__ ((aligned(4)));//为图片显示设定缓存,缓存要4字节对齐，并且要足够大
	//调用图片解码和显示函数
	res=SysLcdDisplayPicture(ImageBuffer,//指向本次解压工作区的指针(4字节对齐)
			                     sizeof(ImageBuffer));//解压工作区的大小
	SetDisplayPictureFlag(0);
	SetDisplayPictureState(res);
	os_lcd_task_exit_critical();//os_port_exit_critical();//退出临界
	return res;
}
int StartDisplayPicture(int x,int y,//图片起始坐标X=0-239，Y=0-319
												const char* filename,//图片文件的名称(字符串类型),名称不能有中文，图片名称不能超过8个字节,后缀不能超过3个字节
												char scale)//图像缩放比例0-3 : 1,1/2,1/4,1/8
{
	SetDisplayPictureBuffer(x,y,filename,scale);
	//先设定相关函数
	SetDisplayFunHook(0,Address_set);
	SetDisplayFunHook(1,LCD_Write_Data16Bit);
	SetDisplayFunHook(2,SetCS);
	SetDisplayFunHook(5,UI_Display_Jpeg);
	SetDisplayFunHook(6,UI_Display_Bmp);
	SetDisplayFunHook(7,Call_DisplayPicture);
	//SetTaskSuspendOtherFunHook(OS_PicTaskSuspend);
	Create_PicTask();

	vPortYield();//让出任务,执行显示任务
}
#endif
#endif