/*
 * lcd_5110_solution.c
 *
 *  Created on: 2012-2-2
 *      Author: Administrator
 */
#include "lcd_5110_solution.h"
#include "main.h"
#include "Delay.h"
#include "SPI-SD/Lcd/font.h"
#include "SPI-SD/Fatfs/ff.h"

char n5110_string[6][14];	//6行，每行13byte

#define CMD		0x00
#define DATA	0x01
#define LCD_X	84
#define LCD_Y	48

#define MAX_HZ_POSX LCD_X
#define MAX_HZ_POSY LCD_Y
#define MAX_CHAR_POSX LCD_X
#define MAX_CHAR_POSY LCD_Y 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////*				以下是基本操作和初始化函数				*//////
#if 0
//write a byte
void LcdWrite(alt_u8 data,alt_u8 d_c)
{
	alt_u8 i;
	//chose the chip
	IOWR_ALTERA_AVALON_PIO_DATA(SCE_BASE, 0x00);
	//chose data mode or command mode
	IOWR_ALTERA_AVALON_PIO_DATA(D_C_BASE, d_c);
	//sent 8 bits
	for(i = 0;i < 8;i ++)
	{
		IOWR_ALTERA_AVALON_PIO_DATA(SCLK_BASE, 0x00);
		IOWR_ALTERA_AVALON_PIO_DATA(SDIN_BASE, data >> (7 - i));
		IOWR_ALTERA_AVALON_PIO_DATA(SCLK_BASE, 0x01);
	}
	//release the chip
	IOWR_ALTERA_AVALON_PIO_DATA(SCE_BASE, 0x01);
}
//initial the 5110
void InitLcd()
{
	usleep(1000);
	//sent a reset pulse(low) to reset all internal registers
	IOWR_ALTERA_AVALON_PIO_DATA(REST_BASE, 0x00);
	usleep(1);
	IOWR_ALTERA_AVALON_PIO_DATA(REST_BASE, 0x01);
	usleep(1);
	//chose the chip
	IOWR_ALTERA_AVALON_PIO_DATA(SCE_BASE, 0x00);
	usleep(1);
	//release the chip
	IOWR_ALTERA_AVALON_PIO_DATA(SCE_BASE, 0x01);
	usleep(1);
	//function set PD = 0 and V = 0, select extended instruction set(H = 1 mode)
	LcdWrite(0x21,CMD);
	//set VOP: VOP is set to a + 65 × b [V]
	LcdWrite(0xbf,CMD);
	//RECOMMENDED MUX RATE(1:24),you can chose other MUX RATE
	LcdWrite(0x15,CMD);
	//function set PD = 0 and V = 0, select normal instruction set(H = 0 mode)
	LcdWrite(0x20,CMD);
	//display control set normal mode (D=1andE=0)
	LcdWrite(0x0c,CMD);
	//clear screen
	LcdClearAll();
}


#else
//write a byte
void LcdWrite(alt_u8 data,alt_u8 d_c)
{
	alt_u8 i;
	//chose the chip
	LCD_CE = 0;					// 使能LCD
	//chose data mode or command mode
	LCD_DC = d_c?1:0;			//0.命令;1.数据
	//sent 8 bits
	for(i = 0;i < 8;i ++)
	{
        SCLK = 0;
        SDIN = (data&(1<<(7-i)))?1:0;
        SCLK = 1;
	}
	//release the chip
	LCD_CE = 1;					// 关闭LCD
}

//initial the 5110
void InitLcd(void)
{
    delay_ms ( 1 );
	//sent a reset pulse(low) to reset all internal registers
    LCD_RST = 0;
    delay_us ( 1 );	// 产生一个让LCD复位的低电平脉冲
    LCD_RST = 1;

	//chose the chip
	delay_us ( 1 );
    LCD_CE = 0;// 关闭LCD
	//release the chip
	delay_us ( 1 );
    LCD_CE = 1;// 使能LCD
	delay_us ( 1 );
#if 0
	//function set PD = 0 and V = 0, select extended instruction set(H = 1 mode)
	LcdWrite(0x21,CMD);
	//set VOP: VOP is set to a + 65 × b [V]
	LcdWrite(0xbf,CMD);
	//RECOMMENDED MUX RATE(1:24),you can chose other MUX RATE
	LcdWrite(0x15,CMD);
	//function set PD = 0 and V = 0, select normal instruction set(H = 0 mode)
	LcdWrite(0x20,CMD);
	//display control set normal mode (D=1andE=0)
	LcdWrite(0x0c,CMD);
	//clear screen
	LcdClearAll();
#else
    LcdWrite ( 0x21, 0 );	// 使用扩展命令设置LCD模式
    LcdWrite ( 0xc8, 0 );	// 设置偏置电压
    LcdWrite ( 0x06, 0 );	// 温度校正
    LcdWrite ( 0x13, 0 );	// 1:48
    LcdWrite ( 0x20, 0 );	// 使用基本命令
    LcdClearAll();	        // 清屏
    LcdWrite ( 0x0c, 0 );	// 设定显示模式，正常显示
#endif	
    //开启背光灯
    BACKLIGHT = 1;
}

#endif
//set the x axis and y axis
void SetXY(alt_u8 x,alt_u8 y)
{
	if(x > 83) x = 0;
	if(y > 5) y = 0;
	//set y axis
	LcdWrite(0x40 | y,CMD);
	//set y axis
	LcdWrite(0x80 | x,CMD);
}
//clear all screen
void LcdClearAll()
{
	alt_u16 i;
	SetXY(0,0);
	//write space continually
	for(i = 0;i < LCD_X * LCD_Y / 8;i ++)
	{
		LcdWrite(0,DATA);
	}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////*				以下是高度为8的各种操作函数				*//////
//*			包括6*8字符和字符串，6*8符号，10*8图标			   *//
//every row contains 14 characters,there are 6 rows (font = 6 * 8)//
/////////////////////////////////////////////////////////////////////////////////////////////////////
		/////////   	x		  /////////
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 0
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 1
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 2
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 3
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 4
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 5
/////////////////////////////////////////////////////////////////////////////////////////////////////
//write a char(6*8),don't need coordinates
void WriteChar(alt_u8 value)
{
	alt_u8 i;
	for(i = 0;i < 6;i ++)
	LcdWrite(ASCII_6_8[value - 0x20][i],DATA);
}
//write a char(6*8),need coordinates
void PutChar(alt_u8 value,alt_u8 x,alt_u8 y)
{
	if(x > 13) x = 0;
	SetXY(6 * x,y);
	WriteChar(value);
}
//write a string(6*8),don't need coordinates
void WriteStr(char * str)
{
	while(*str)
	{
		WriteChar(*str ++);
	}
}
//write a string(6*8),need coordinates,auto line breaks
void PutStr(char * str,alt_u8 x,alt_u8 y)
{
	if(x > 13) x = 0;
	SetXY(6 * x,y);
	WriteStr(str);
}
//draw a sign(6*8),don't need coordinates
void WriteSign(char * sign)
{
	alt_u8 i;
	for(i = 0;i < 6;i ++)
	LcdWrite(sign[i],DATA);
}
//draw a sign(6*8),need coordinates
void DrawSign(char * sign,alt_u8 x,alt_u8 y)
{
	SetXY(x,y);
	WriteSign(sign);
}
//draw a sign(10*8),don't need coordinates
void WriteIcon(char * icon)
{
	alt_u8 i;
	for(i = 0;i < 10;i ++)
	LcdWrite(icon[i],DATA);
}
//draw a sign(10*8),need coordinates,x is between 0 and 74
void DrawIcon(char * icon,alt_u8 x,alt_u8 y)
{
	//if need line breaks
	if(x > 74)
	{
		x = 0;
		y += 1;
	}
	SetXY(x,y);
	//draw a sign(10*8)
	WriteIcon(icon);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////*				以下是高度为16的各种操作函数				*//////
//*		    	      包括8*16字符和字符串，16*16汉字		           *//
//every row contains 10 characters,there are 3 rows (font = 8 * 16)//
///////////////////////////////////////////////////////////////////////////////////////////////////
/////////       x       ///////////
		//0 1 2 3 ... 81 82 83//	y = 0
		//0 1 2 3 ... 81 82 83//
		//0 1 2 3 ... 81 82 83//	y = 1
		//0 1 2 3 ... 81 82 83//
		//0 1 2 3 ... 81 82 83//	y = 2
		//0 1 2 3 ... 81 82 83//
///////////////////////////////////////////////////////////////////////////////////////////////////
//write a char(8*16)
void WriteChar_8_16(alt_u8 value,alt_u8 x,alt_u8 y)
{
	alt_u8 i;
	//draw the first row
	SetXY(x,y * 2);
	for(i = 0;i < 8;i ++)
		LcdWrite(ASCII_8_16[value - 0x20][i],DATA);
	//draw the second row
	SetXY(x,y * 2 + 1);
	for(i = 8;i < 16;i ++)
		LcdWrite(ASCII_8_16[value - 0x20][i],DATA);
}
//write a string(8*16),auto line breaks,x is between 0 and 76
void WriteStr_8_16(char * str,alt_u8 x,alt_u8 y)
{
	alt_u8 i = 0;
	while(*str)
	{
		//if need line breaks
		if(x + (8 * i) > 76)
		{
			x = 0;
			i = 0;
			y += 2;
		}
		//write a char(8*16)
		WriteChar_8_16(*str,x + (8 * i),y);
		str ++;
		i ++;
	}
}
//every row contains 5 characters,there are 3 rows (font = 16 * 16)//
///////////////////////////////////////////////////////////////////////////////////////////////////
/////////       x       ///////////
		//0 1 2 3 ... 81 82 83//	y = 0
		//0 1 2 3 ... 81 82 83//
		//0 1 2 3 ... 81 82 83//	y = 1
		//0 1 2 3 ... 81 82 83//
		//0 1 2 3 ... 81 82 83//	y = 2
		//0 1 2 3 ... 81 82 83//
///////////////////////////////////////////////////////////////////////////////////////////////////
//write a Chinese character(16*16)
void WriteHanzi(char Hanzi[],alt_u8 x,alt_u8 y)
{
	alt_u8 i;
	//write the first row
	SetXY(x,y * 2);
	for(i = 0;i < 16;i ++)
		LcdWrite(Hanzi[i],DATA);
	//write the second row
	SetXY(x,2 * y + 1);
	for(i = 16;i < 32;i ++)
		LcdWrite(Hanzi[i],DATA);
}
//write a Chinese sentence(16*16),auto line breaks,x is between 0 and 58
void WriteHanziStr(char Hanzi[],alt_u8 x,alt_u8 y,alt_u8 num)
{
	alt_u8 num_i,i = 0;
	for(num_i = 0;num_i < num;num_i ++)
	{
		//if need line breaks
		if(x + (16 * num_i) > 58)
		{
			x = 0;
			i = 0;
			y += 1;
		}
		//write a Chinese character(16*16)
		WriteHanzi(Hanzi + 32 * num_i,x + (16 * i),y);
		i ++;
	}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////*				以下是画图的各种操作函数				*//////
//*		    	      包括84*48,高度为8的倍数的图片		       *//
/////////////////////////////////////////////////////////////////////////////////////////////////////
		/////////   	x		  /////////
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 0
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 1
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 2
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 3
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 4
		//0 1 2 3 4 5 6 7 8 9 10 11 12 13//		y = 5
/////////////////////////////////////////////////////////////////////////////////////////////////////
//draw a picture(84*48),don't need coordinates
void DrawPicture(char bitmap[])
{
	alt_u16 i;
	for(i = 0;i < LCD_X * LCD_Y / 8;i ++)
		LcdWrite(bitmap[i],DATA);
}

//列行扫描(每列=8bit，n行)
//draw a picture(width*height(a multiple of 8)),need coordinates
void DrawBitmap(char bitmap[],alt_u8 x,alt_u8 y,alt_u8 width,alt_u8 height)
{
	alt_u8 width_i,height_i;
	//draw the height_i row
	for(height_i = 0;height_i < height / 8;height_i ++)
	{
		SetXY(x,y + height_i);
		//draw a row(width column)
		for(width_i = 0;width_i < width;width_i ++)
		{
			LcdWrite(bitmap[width_i + height_i * width],DATA);
		}
	}
}

//列扫描
void DrawBitmap_col(char bitmap[],alt_u8 x,alt_u8 y,alt_u8 width,alt_u8 height)
{
	alt_u8 i,j,z;

	if(height%8 == 0)	//必须是8bit的整数倍
	{
		for(i=0; i<width; i++)
		{
			for(j=0; j<height/8; j++)
			{
                SetXY(x+i, y+j);//换行列                
				LcdWrite(bitmap[z++], DATA);//写最小一列(8bit)
			}
		}
	}
}

#define LCD_Clear(x) LcdClearAll()
/*********************************************************************************
	名称：void LCD_ShowCharString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t PenColor, uint16_t BackColor)
	参数：x，y      起始坐标
	      p         指向字符串起始地址
				PenColor  字符颜色
				BackColor 背景颜色
	功能：
	备注：用16字体，可以调节 此函数不能单独调用
*********************************************************************************/
void LCD_ShowCharString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t PenColor, uint16_t BackColor)
{   
	uint8_t size = 16;     /*---字符大小默认16*8---*/
	 
    if(x>MAX_CHAR_POSX){x=0;y+=size;}			         /*超出X轴字体最小单位，换行*/
    if(y>MAX_CHAR_POSY){y=x=0;LCD_Clear(WHITE);}	 /*超出Y轴字体最小单位，回到原点，并且清屏*/
    //LCD_ShowChar(x, y, *p, size, PenColor, BackColor);			   /*0表示非叠加方式*/
	PutChar(*p ,x, y);
	//WriteChar_8_16(*p ,x, y);
}


/*********************************************************************************
	*名称: u16 findHzIndex(u8 *hz)
	*参数：hz
	*功能：索引汉字存储的内存地址
	*备注：
*********************************************************************************/
u16 findHzIndex(u8 *hz)                            /* 在自定义汉字库在查找所要显示 */
                                                      /* 的汉字的位置 */
{
	u16 i=0;
	FNT_GB16 *ptGb16 = (FNT_GB16 *)GBHZ_16;		  /*ptGb16指向GBHZ_16*/
	while(ptGb16[i].Index[0] > 0x80)
	{
	    if ((*hz == ptGb16[i].Index[0]) && (*(hz+1) == ptGb16[i].Index[1])) /*汉字用两位来表示地址码*/
			{
	      return i;
	    }
	    i++;
	    if(i > (sizeof((FNT_GB16 *)GBHZ_16) / sizeof(FNT_GB16) - 1))  /* 搜索下标约束 */
	    {
		    break;
	    }
	}
	return 0;
}

#if 0
/*********************************************************************************
	*名称：void WriteOneHz(uint16_t x0, uint16_t y0, uint8_t *pucMsk, uint16_t PenColor, uint16_t BackColor)
	*参数：x0,y0     起始坐标
		     *pucMsk   指向
				 PenColor	 字符颜色
				 BackColor 背景颜色
	*功能：
	*备注：此函数不能单独作为汉字字符显示											  
*********************************************************************************/					
void WriteOneHz(u16 x0, u16 y0, u8 *pucMsk, u16 PenColor, u16 BackColor)
{
    u16 i,j;
    u16 mod[16];                                      /* 当前字模 16*16 */
    u16 *pusMsk;                                      /* 当前字库地址  */
    u16 y;
		u16 size = 16;       /*汉字默认大小16*16*/

    pusMsk = (u16 *)pucMsk;

    for(i=0; i<16; i++)                                    /* 保存当前汉字点阵式字模       */
    {
			mod[i] = *pusMsk;                                /* 取得当前字模，半字对齐访问   */
			mod[i] = ((mod[i] & 0xff00) >> 8) | ((mod[i] & 0x00ff) << 8);/* 字模交换高低字节*/
			pusMsk = pusMsk+1;
    }
    y = y0;
		LCD_WindowMax(x0,y0,x0+size,y0+size);	 	/*设置窗口*/
		LCD_SetCursor(x0,y0);                       /*设置光标位置 */ 
		LCD_WriteRAM_Prepare();                     /*开始写入GRAM*/  
    for(i=0; i<16; i++)                                    /* 16行   */
    {                                              
      for(j=0; j<16; j++)                                /* 16列   */
      {
		    if((mod[i] << j) & 0x8000)       /* 显示第i行 共16个点 */
        { 
			    LCD_WriteRAM(PenColor);
        } 
				else 
				{
          LCD_WriteRAM(BackColor);      /* 用读方式跳过写空白点的像素*/
				}
      }
        y++;
    }
	LCD_WindowMax(0x0000,0x0000,240,320);  	/*恢复窗体大小*/
}
#endif


/*********************************************************************************
	*名称：void LCD_ShowHzString(u16 x0, u16 y0, u8 *pcStr, u16 PenColor, u16 BackColor)
	*参数：x0，y0    起始坐标
				 pcStr     指向
				 PenColor  字体颜色
				 BackColor 字体背景
	*功能：显示汉字字符串
	*备注：这个函数不能单独调用	       
*********************************************************************************/
void LCD_ShowHzString(u16 x0, u16 y0, u8 *pcStr, u16 PenColor, u16 BackColor)
{
 
	u16 usIndex;
	u8 size = 16; 
	FNT_GB16 *ptGb16 = 0;    
    ptGb16 = (FNT_GB16 *)GBHZ_16; 

	if(x0>MAX_HZ_POSX){x0=0;y0+=size;}			         /*超出X轴字体最小单位，换行*/
    if(y0>MAX_HZ_POSY){y0=x0=0;LCD_Clear(WHITE);}	   /*超出Y轴字体最小单位，回到原点，并且清屏*/

	usIndex = findHzIndex(pcStr);
	//WriteOneHz(x0, y0, (u8 *)&(ptGb16[usIndex].Msk[0]),  PenColor, BackColor); /* 显示字符 */
	WriteHanzi((char *)&(ptGb16[usIndex].Msk[0]), x0, y0);
}

/*********************************************************************************
	*名称：void LCD_ShowString(u16 x0, u16 y0, u8 *pcstr, u16 PenColor, u16 BackColor)
	*参数：x0 y0     起始坐标
				 pcstr     字符串指针
				 PenColor  字体颜色
				 BackColor 字体背景色
	*功能：调用字符和汉字显示函数，实现字符串显示
	*备注：	
*********************************************************************************/
void LCD_ShowString(u16 x0, u16 y0, u8 *pcStr, u16 PenColor, u16 BackColor)
{
	while(*pcStr!='\0')
	{
	 	if (x0>MAX_HZ_POSX)	/*保证剩余的空间能放下一个16*16的字，否则换行 */
			{
				y0+=16;
				x0=0;
			}
			if (y0>MAX_HZ_POSY)	/*保证剩余的空间能放下一个16*16的字，否则换行 */
			{
				y0=0;
			}
		if(*pcStr>0x80) /*显示汉字*/
		{
			LCD_ShowHzString(x0, y0, pcStr, PenColor, BackColor);
			pcStr += 2;
			x0 += 16;	
		}
		else           /*显示字符*/
		{
			LCD_ShowCharString(x0, y0, pcStr, PenColor, BackColor);	
			pcStr +=1;
			x0+= 8;
		}	
	}	
}


void RefreshLCD ( void )
{
#if LCD_def
    u8 i;
    for ( i = 0; i < 6; i++ )
    {
    	PutStr(n5110_string[i], 0, i);
    }
#endif	
}

/*--------------下面三个函数 实现字库的调用及显示-------------------*/
FATFS fs;
FIL fsrc;      /* file objects  */
UINT br;         // File R/W count
enum ziType{
	ziType_12,
	ziType_16,
	ziType_24,
	ziType_Max
};
static u8 SPI_FLASH_BufferRead(char* getStr, char* zi, char ziType)
{
	FRESULT res;
	u8 error[]="Cann't file HZK bin.";
	u8 zi_h = zi[0];
	u8 zi_l = zi[1];
	unsigned long int findAddr, ziSize;
	if(ziType == ziType_12){//12*12	= 24
		findAddr = (unsigned long int)(((zi_h-0xa1)*94)+(zi_l-0xa1))*24;
		ziSize = 24;
	}
	else if(ziType == ziType_16){//16*16 = 32
		findAddr = (unsigned long int)(((zi_h-0xa1)*94)+(zi_l-0xa1))*32+(unsigned long int)0x2FEB0;
		ziSize = 32;
	}
	else if(ziType == ziType_24){//24*24 = 72
		findAddr = (unsigned long int)(((zi_h-0xa1)*94)+(zi_l-0xa1))*72+(unsigned long int)0x6FCF0;
		ziSize = 72;
	}
	else	
		return 0;
	
	f_mount(0, &fs);

	//HZK16.bin
	/* Infinite loop */
	res = f_open(&fsrc, "/sys/HZK.bin", FA_OPEN_EXISTING | FA_READ);	 /* 在SD卡里搜索HZK16.bin*/
	if(res != 0)
	{
		PutStr((char *)error, 0, 0);
		return 0;
	}

	f_lseek(&fsrc, findAddr);
	f_read(&fsrc, getStr, ziSize, &br);
		
	f_close(&fsrc);	
	f_mount(0, NULL);
	
	return 1;
}

static uint8_t Find_Chinese(uint8_t* str, uint8_t* p)
{
	uint8_t High8bit,Low8bit;
	FRESULT res;
	uint8_t error[]="Please put the sys folder which include the font file HZK16.bin into the SD  card  root directory. ";
	High8bit=*str;		 /*  高8位数据  */
	Low8bit=*(str+1);		 /*  低8位数据	*/
	
	f_mount(0, &fs);

	//HZK16.bin
	/* Infinite loop */
	res = f_open(&fsrc, "/sys/ZK_1212_1616_2424.bin", FA_OPEN_EXISTING | FA_READ);	 /* 在SD卡里搜索HZK16.bin*/
	if(res != 0)
	{
		LCD_ShowString(0,0,error,RED ,BLACK );
		return 0;
	}

	f_lseek(&fsrc,32*((High8bit-0xa0-1)*94+(Low8bit-0xa0-1)));
	f_read(&fsrc, p, 32, &br);
		
	f_close(&fsrc);	
	f_mount(0, NULL);
	
	return 1;	
}


/*********************************************************************************
* 名    称：void PutChinese(u16 x, u16 y, u8 *c, u32 PenColor, u32 BackColor)
* 入口参数：u16 x,u16 y 字符坐标位置
						u8  *c      汉字的指针
						u32 PenColor画笔颜色
						u32 BackColor背景颜色
* 出口参数：无
* 功    能：从SPI_FLASH里查找汉字基地址，
						并将32字节的点阵数据送到LCD显示
* 说    明：只能被GUI_Put调用
*********************************************************************************/
u8 buffer_r[32];
u8 *c_r;
void PutChinese(u16 x, u16 y, u8 *c, u32 PenColor, u32 BackColor)
{
	//u16 i=0;
	//u16 j=0;

	u8 buffer[32];
	//u16 tmp_char=0;

	if(!Find_Chinese(c,buffer))
	{
		c_r = c;
		memcpy(buffer_r,buffer,32);
		WriteHanzi((char *)&buffer, x, y);
		#if 0
		LCD_WindowMax(x,y,x+16,y+16);	 	/*设置窗口*/
		LCD_SetCursor(x,y);                       /*设置光标位置 */ 
		LCD_WriteRAM_Prepare();

		/* 16*16汉字点阵，共有16行 每行16个点，存储的时候是以字节为单位
			 需合并成字*/
		for (i=0;i<16;i++)		 
		{
			tmp_char=buffer[i*2];
			tmp_char=(tmp_char<<8);
			tmp_char|=buffer[2*i+1];  /*现在tmp_char存储着一行的点阵数据*/

			for (j=0;j<16;j++)
			{
				if((tmp_char<<j) & 0x8000)
					LCD_WriteRAM(PenColor);
				else
					LCD_WriteRAM(BackColor);
			}
		}
		LCD_WindowMax(0x00,0x00,240,320);  	/*恢复窗体大小*/
		#endif
	}
}

//逐行式 转列行式
/*
	 
0040                                           11                        
4048            11                            11        11            
37FC                1111    111111111111111111        
1040                    11                    11                        
0044                                           11            11        
0FFE                        1111111111111111111111    
0910                        11        11            11                
128C                    11        11    11            1111        
24F4                11        11        11111111    11        
E110        111111                11            11                
2310                11            1111            11                
24A0                11        11        11    11                    
2840                11    11                11                        
20A0                11                    11    11                    
231E                11            1111            11111111    
0C04                        1111                            11        	  

	汉字库格式:逐行式
	byte1 byte2		[1 2 3 4 5 6 7 8] [9 10 11 12 13 14 15 16]
	byte3 byte4
	***** *****
	转化:
	u16[0]			[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]

	转化:
	u16[0]			[1]
					[2]	
					[3] 
					**
					[16]
					
	转化:
	u8[0]	u8[2]	u8[4]	u8[6]	u8[8]	u8[10]	u8[12]	u8[14]
	u8[1]	u8[3]	u8[5]	u8[7]	u8[9]	u8[11]	u8[13]	u8[15]	

	转化:
	u8[0]	u8[1]	u8[2]	u8[3]	u8[4]	u8[5]	u8[6]	u8[7]
	u8[8]	u8[9]	u8[10]	u8[11]	u8[12]	u8[13]	u8[14]	u8[15]

					
	5110显示格式:阴码，列行式，逆向(低位在前)
	1.一列八点阵
	2.低位在前
	byte1	[1] 		byte2	[9]		byte3	[17] 		byte4	[25]
			[2] 				[10]				[18] 				[26]
			[3] 				[11]				[19] 				[27]
			[4] 				[12]				[20] 				[28]
			[5] 				[13]				[21] 				[29]
			[6] 				[14]				[22] 				[30]
			[7] 				[15]				[23] 				[31]
			[8] 				[16]				[24] 				[32]
*/

u8 ReturnHzNum(u8 in)
{
	if(in<16)
	{
		if(in<8)	return (2*in);
		else		return (2*(in-8)+1);	
	}
        return 0xFF;
}

void xing2lie(u8 inBuffer[])
{
	u16 HzkBuffer[16]={0};	
	u16 PlayBuffer[16]={0};	
	u8 outBuffer2[32]={0};
	u8 res;
	u8 i, j;

	for (i=0;i<16;i++)		 
	{
		HzkBuffer[i] = inBuffer[i*2]<<8 | inBuffer[2*i+1];
	}
	
	for(i=0;i<16;i++)
	{
		for(j=0;j<16;j++)
		{
			res = HzkBuffer[j]>>(15-i)?1:0;
			PlayBuffer[i] |= res<<(15-j);
		}
	}

	for (i=0;i<16;i++)		 
	{
		outBuffer2[i*2] = (PlayBuffer[i]&0xFF00)>>8;
		outBuffer2[i*2+1] =	PlayBuffer[i]&0x00FF;
	}


	memcpy(inBuffer, outBuffer2, 32);
}

char hz_1[][32]={
	// 我(0) 们(1)
	
	{0x04,0x20,0x04,0x20,0x44,0x42,0x44,0x41,0x7F,0xFE,0x84,0x80,0x84,0x80,0x04,0x08,
	0x04,0x08,0xFF,0x10,0x04,0xE0,0x44,0x58,0x35,0x84,0x04,0x02,0x04,0x0F,0x00,0x00},/*"我",0*/
	
	{0x01,0x00,0x02,0x00,0x0F,0xFE,0x38,0x00,0xC0,0x00,0x0F,0xFE,0x80,0x00,0x70,0x00,
	0x20,0x00,0x00,0x00,0x20,0x00,0x20,0x04,0x20,0x02,0x3F,0xFC,0x00,0x00,0x00,0x00},/*"们",1*/

	{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
	 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},/*"们",1*/

};
/*********************************************************************************
* 名    称：void GUI_Put(u16 x, u16 y, u8 *str,u32 PenColor, u32 BackColor)
* 入口参数：u16 x,u16 y 字符坐标位置
						u8  *c      汉字的指针
						u32 PenColor画笔颜色
						u32 BackColor背景颜色
* 出口参数：无
* 功    能：计算汉字显示坐标
* 说    明：
*********************************************************************************/
char hzk_buffer[32];
void DispOneChs12x12(u8 row,u8 addr,u8 *p);
void GUI_Put(u16 x, u16 y, u8 *str,u32 PenColor, u32 BackColor)
{  
	//x:0~84  y:0~6
	do
	{
		if ( *str < 0x80) /* 显示字符，字符点阵直接从font.h里调用，大小为16*8 */
		{
			if (x>LCD_X)	/*保证剩余的空间能放下一个16*16的字，否则换行 */
			{
				y+=1;
				x=0;
			}
			if (y>LCD_Y)	/*保证剩余的空间能放下一个16*16的字，否则换行 */
			{
				y=0;
			}
			
			//6*8
			DrawBitmap((char *)&ASCII_6_8[*str - 0x20][0], x, y, 6, 8);
			x+=6;
			str++;   
		}
		else	                /*大于等于0x80判断为汉字字符*/
		{ 
			if (x>LCD_X-12)	/*保证剩余的空间能放下一个16*16的字，否则换行 */
			{
				y+=1;
				x=0;
			}
			if (y>LCD_Y-1)	/*保证剩余的空间能放下一个16*16的字，否则换行 */
			{
				y=0;
			}

			#if 0
			//16*16
			if(Find_Chinese(str, hzk_buffer))
			{
				xing2lie(hzk_buffer);
				DrawBitmap_col(hzk_buffer, x, y, 16, 16);
				//DrawBitmap(hzk_buffer, x, y, 16, 16);
			}
			#else
			if(SPI_FLASH_BufferRead(hzk_buffer,(char *)str,ziType_12))
			{
				//DrawBitmap(hzk_buffer, x, y, 16, 16);
				DispOneChs12x12(y, x, hzk_buffer);
			}
			#endif
			x+=12;//16; 
			str += 2;	
			delay_ms(500);
		}
	}while(*str!=0);
}

/**********************************************************************/

u8 Y0Ram[84]; //第0行汉字的临时缓存
u8 Y1Ram[84];
u8 Y2Ram[84];
u8 Y3Ram[84];

#define Lcd5110SetXY(x,y) SetXY(x,y)
#define Lcd5110WriteDta(x) LcdWrite(x,DATA) 
/*---------------------------------------------
              在某行某地址显示中文字符,
-----------------------------------------------*/
void DispOneChs12x12(u8 row,u8 addr,u8 *p)
{

        u8 i, LocalHalfWidth,LocalFullWidth; //半宽字体,全宽字体
        if (row==0)//按照4行显示,首行为0,地址就是0-3行,不是控制器的地址
        {
                Lcd5110SetXY(addr, row);// 列，页
                for (i=0; i<12;i++) //上半部分 12个像素
                {
                        Lcd5110WriteDta(p[i]);
                }
                Lcd5110SetXY(addr, row+1);

                /*字体的下半部分需要存储起来*/
                for (i=12; i<24;i++) //下半部分 12个像素
                {
                        Y0Ram[addr+i-12]=p[i]; //第0行的下半部分12个字节存起来,数组要保存文字的下半部分和这些数据在什么位置 0-83
                        Lcd5110WriteDta(Y0Ram[addr+i-12] | Y1Ram[addr+i-12]<<4 );
                }

        }
        if (row==1)
        {
                Lcd5110SetXY(addr, row);// 列，页
                for (i=0; i<12;i++) //上半部分 12个像素
                {
                        Y1Ram[addr+i]=p[i];//第1行上半部分存起来
                        Lcd5110WriteDta(Y1Ram[ addr+i]<<4 |Y0Ram[addr+i]);
                }
                Lcd5110SetXY(addr, row+1);// 列，页
                for (i=12; i<24;i++) //下半部分 12个像素
                {
                        Lcd5110WriteDta(p[i]<<4 | p[i-12]>>4  );
                }

        }
        if (row==2)//按照4行显示,首行为0,地址就是0-3行,不是控制器的地址
        {
                Lcd5110SetXY(addr, row+1);// 列，页
                for (i=0; i<12;i++) //上半部分 12个像素
                {
                        Lcd5110WriteDta(p[i]);
                }
                Lcd5110SetXY(addr, row+2);

                /*字体的下半部分需要存储起来*/
                for (i=12; i<24;i++) //下半部分 12个像素
                {
                        Y2Ram[addr+i-12]=p[i]; //第0行的下半部分12个字节存起来,数组要保存文字的下半部分和这些数据在什么位置 0-83
                        Lcd5110WriteDta(Y2Ram[addr+i-12] | Y3Ram[addr+i-12]<<4 );
                }

        }
        if (row==3)
        {
                Lcd5110SetXY(addr, row+1);// 列，页
                for (i=0; i<12;i++) //上半部分 12个像素
                {
                        Y3Ram[addr+i]=p[i];//第1行上半部分存起来
                        Lcd5110WriteDta(Y3Ram[ addr+i]<<4 |Y2Ram[addr+i]);
                }
                Lcd5110SetXY(addr, row+2);// 列，页
                for (i=12; i<24;i++) //下半部分 12个像素
                {
                        Lcd5110WriteDta(p[i]<<4 | p[i-12]>>4  );
                }

        }

}

