#include "includes.h" extern const unsigned char g_apucLetter16[]; extern const unsigned char g_apucCLetter16[]; extern const unsigned char g_apucLetter24[]; extern const unsigned char g_apucCLetter24[]; extern const unsigned char g_apucFonts16[]; extern const unsigned char g_apucCFonts16[]; extern const unsigned char g_apucFonts24[]; extern const unsigned char g_apucCFonts24[]; extern const unsigned char g_apucFonts12[]; extern const unsigned char g_apucLetter12[]; SUT_HZK sutHzk16; SUT_HZK sutHzk12; unsigned char g_Palette[256*4];//调色板 顺序是BGRA 其中A未用 u8 g_ucWarnColorId; //警告颜色 u8 g_ucForeColorId; //画笔颜色索引 u8 g_ucBackColorId; //背景颜色索引 u8 g_ucSel_ColorId; //选定区域颜色索引 u16 g_usWarnColor;//警告色 u16 g_usForeColor;//前景色 RGB565值 需要根据颜色索引从当前调色板中获取 u16 g_usBackColor;//背景色 RGB656值 需要根据颜色索引从当前调色板中获取 void PaintToBuf(u16 x,u16 y,u16 width,u16 heigh,u8 *data); void PaintBufToLcd(u16 x,u16 y,u16 width,u16 heigh,unsigned char colorID); u16 RGB888toRGB565(unsigned char R,unsigned char G, unsigned char B); void SetPaletteByBmpFile(char *filename); void UpdateColor(void); void GuiDrawDot(u16 x,u16 y); void UpdateDot(unsigned char colorID); /*************************************************************************** 在调色板中查找与期望颜色最接近的颜色并返回其索引 输入:ColorRGB 格式:0xRRGGBB 红绿蓝 返回:在调色板中,最接近ColorRGB的颜色索引 算法:对调色板内的每个色素点分别求出RGB之差的绝对值并求和,然后找出最小值所对应的色素点的索引即可 ****************************************************************************/ int FindColorIndex(unsigned long ColorRGB) { int i,j,k; int R,G,B; int fR,fG,fB;//计算期望RGB和调色板内每个RGB差的绝对值 int fSum,fSumMin; R=(int)((ColorRGB>>16)&0xff); G=(int)((ColorRGB>>8)&0xff); B=(int)(ColorRGB&0xff); fSumMin=999999; k=0; for(i=0;i<256;i++){ j=i*4; fB=g_Palette[j]; fG=g_Palette[j+1]; fR=g_Palette[j+2]; //g_Palette[j+3]未用 fB=B-fB;//B差 if(fB<0)fB=-fB; //B差的绝对值 fG=G-fG;//G差 if(fG<0)fG=-fG;//G差的绝对值 fR=R-fR;//R差 if(fR<0)fR=-fR;//R差的绝对值 //RGB差的绝对值求和 fSum=fB+fG+fR; //找到RGB差的绝对值之和的最小值 if(fSum>3; // 取R色的高5位 g = G>>2; // 取G色的高6位 b = B>>3; // 取B色的高5位 return( (r<<11) + (g<<5) + (b<<0) ); } /***************************************** 从字库文件HZK16中提取某汉子的字库数据 输入:hiByte--汉字的高字节 loByte--汉字的低字节 字库文件存储在sFlash中,字库文件名为HZK16 输出:pHzk--提取到的字库数据,需要预留足够空间存储。如果是16*16 则应该是16*16/8=32Byte 返回:失败返回0 成功返回长度 ******************************************/ int GetHzk(u8 hiByte,u8 loByte,u8 *pHzk,u8 font) { u8 Q,W; u32 offset; if(hiByte<0xa0 || loByte<0xa0)return 0; Q=hiByte-0xa0; W=loByte-0xa0; if(!font) { offset=(94 * (Q-1) + (W-1))* 24; return ReadFileData(sutHzk12.FileIndex,offset,24,pHzk); }else { offset=(94 * (Q-1) + (W-1))* 32; return ReadFileData(sutHzk16.FileIndex,offset,32,pHzk); } } /****************************************** *汉子库初始化 *输入:汉字库文件名 *输出:汉字库数据首地址存放在sHZK16中 *返回:1--成功 0--失败,找不到文件 *******************************************/ int HzkInit(const char *filename) { int i; if(g_sutFilesList.FileCount==0)return 0; if(!strcmp(filename,"HZK16")) { memset(&sutHzk16,0,sizeof(SUT_HZK)); i=GetFileIndex(filename); if(i<0)return 0; sutHzk16.width=16; sutHzk16.heigh=16; sutHzk16.len=(sutHzk16.width * sutHzk16.heigh)/8; sutHzk16.FileIndex=i; sutHzk16.FileLen=g_sutFilesList.FileInfo[i].FileLen; return 1; }else if(!strcmp(filename,"HZK12")){ memset(&sutHzk12,0,sizeof(SUT_HZK)); i=GetFileIndex(filename); if(i<0)return 0; sutHzk12.FileIndex=i; sutHzk12.FileLen=g_sutFilesList.FileInfo[i].FileLen; return 1; } } void GuiClearAll(void) { GuiFillRect(0,STATUS_BAR_HEIGH,159,STATUS_ITEM_HEIGH-1,COLOR_WARN_RED); PaintBufToLcd(0,STATUS_ITEM_HEIGH,LCD_WIDTH,LCD_HEIGHT,g_ucBackColorId); } /****************************************** GuiInit 初始化GUI *******************************************/ void GuiInit(void) { if(!HzkInit(HZK16_FILE_NAME)) { printf("Can't find the Hzk16File(%s)!\r\n",HZK16_FILE_NAME); } if(!HzkInit(HZK12_FILE_NAME)) { printf("Can't find the Hzk12File(%s)!\r\n",HZK12_FILE_NAME); } //设置默认调色板 //GuiSetDefaultPalette();//设置系统调色板为程序代码中预设的调色板 SetPaletteByBmpFile("allpic.bmp");//从指定BMP文件中提取调色板作为系统调色板 //设置前景色和背景色,设置前景色和背景色前需要先设置调色板 GuiSetColor(COLOR_DARKBLUE,COLOR_WHITE,COLOR_RED,COLOR_SEL_BULUE); //清空所有显示区域,即将所有显示区域设置为背景色 //GuiClearAll(); GuiShowBmp(0,0,"welcome.bmp"); //GuiShowBmp(0,0,"Palace0.bmp"); } /************************************************************ GuiPainToBuf 将位图数据刷到显示缓冲区 位图数据按:每行从左到右,从上行到下行扫描 *************************************************************/ void PaintToBuf(u16 x,u16 y,u16 width,u16 heigh,u8 *data) { int i,j,k,t; unsigned short RGB565; unsigned char R,G,B; unsigned short r,g,b; for(j=0;j>3; // 取R色的高5位 g = G>>2; // 取G色的高6位 b = B>>3; // 取B色的高5位 RGB565=((r<<11) + (g<<5) + (b<<0)); LcdSendData(RGB565 >> 8); LcdSendData(RGB565 & 0xff); } } } /************************************************************ PaintBufToLcd 将显示缓冲区的数据刷到LCD显示 *************************************************************/ void PaintBufToLcd(u16 x,u16 y,u16 width,u16 heigh,unsigned char colorID) { int i,j,k; unsigned short RGB565; unsigned short temp; if(x>=LCD_WIDTH || y>=LCD_HEIGHT)return; if(x+width>LCD_WIDTH)width=LCD_WIDTH-x-1; if(y+heigh>LCD_HEIGHT)heigh=LCD_HEIGHT-y-1; IWDG_ReloadCounter();//防止刷的死机 temp=colorID*4; RGB565=RGB888toRGB565(g_Palette[temp+2],g_Palette[temp+1],g_Palette[temp]); LcdBlockWrite(x,y,x+width-1,y+heigh-1); for(j=0;j> 8); LcdSendData(RGB565 & 0xff); } } } // 12 *12 16*16 void PaintCharToBuf(u16 x,u16 y,u8 hiByte,u8 loByte,u8 mode,u8 rev) { unsigned short i,j,k,m,n; unsigned short width,height; unsigned char ByteWidth,data; unsigned char colorH,colorL; unsigned char bgcolorH,bgcolorL; const unsigned char *l_pucFont,*l_pucLetter; unsigned char *p; unsigned char font;//字体 unsigned char cover;//覆盖方式 unsigned char sucHzk16[32]; unsigned char sucHzk12[24]; unsigned char lcdData; font=mode&0xf0; cover=mode&0x0f; //===先根据字符设置显示的宽、高、点阵数据指针等=== k = 0; if(!hiByte) //english { if(font==0x00) //8* 12 { width=8;//8 height = 12; //12 ByteWidth = 1; l_pucFont = g_apucFonts12; l_pucLetter = g_apucLetter12; }else{ //8*16 width=8; height = 16; ByteWidth = 1; l_pucFont = g_apucFonts16; l_pucLetter = g_apucLetter16; } // while(*l_pucLetter) { if(loByte == *l_pucLetter)break; l_pucLetter ++; k ++; } //查找到字库的开始位置 l_pucFont += k * ByteWidth * height; }else { //chinese if(font == 0x00)//12*16 { width=16; height = 12; ByteWidth = 2; l_pucFont = sucHzk12; l_pucLetter = 0; k=0; if(sizeof(sucHzk12)!=GetHzk(hiByte,loByte,sucHzk12,font)){//从sFlash的HZK文件中读取字库数据 //找不到字库,显示"口" l_pucFont=g_apucCLetter16; } }else{//16*16 width=16; height = 16; ByteWidth = 2; l_pucFont = sucHzk16; l_pucLetter = 0; k=0; if(sizeof(sucHzk16)!=GetHzk(hiByte,loByte,sucHzk16,font)){//从sFlash的HZK16文件中读取字库数据 //找不到字库,显示"口" l_pucFont=g_apucCLetter16; } } // } //====================再处理点阵数据========== if(y+height>LCD_HEIGHT)return; if(x+width>LCD_WIDTH)return; LcdBlockWrite(x,y,x+width-1,y+height-1);//8,12 //以下直接将点阵刷到LCD,不用显存。用于测试,注意调用不要调用PaintBufToLcd,否则也刷屏了 //根据字模在显存中画点 for(j=0;j>k)){//有点,画上前景色 if(m 0x9f) //chinese letter { PaintCharToBuf(x+i,y,*p, *(p+1),mode,rev); i += width1 ; p += 2; } else //english letter { PaintCharToBuf(x + i,y,0,*p,mode,rev); if(font==0){ i += width2 * 8; }else{ i += width2 * 8; } p ++; } } //将内容从显存刷到LCD显示 //PaintBufToLcd(x,y,i,heigh); } // int WidthBytes( int nBits, int nWidth ) { int nWidthBytes; nWidthBytes = nWidth; if( nBits == 1 ) nWidthBytes = ( nWidth + 7 ) / 8; else if( nBits == 4 ) nWidthBytes = ( nWidth + 1 ) / 2; else if( nBits == 16 ) nWidthBytes = nWidth * 2; else if( nBits == 24 ) nWidthBytes = nWidth * 3; else if( nBits == 32 ) nWidthBytes = nWidth * 4; while( ( nWidthBytes & 3 ) != 0 ) nWidthBytes++; return( nWidthBytes ); } /************************************************************ GuiShowBmp 从sFlsh中读取BMP文件并显示 *************************************************************/ void GuiShowBmp(u16 x,u16 y,const char * filename) { int i,w,l; int index; int FileLen; unsigned short type; unsigned int width,heigh,SizeImage,bfOffBits; unsigned char temp[480];//160*3 index=GetFileIndex(filename); FileLen=GetFileLen(index); if(FileLen==0)return;//找不到文件,直接返回不处理 //读出位图类型 ReadFileData(index,28,2,(u8 *)&type);//读出int biBitCount ; // 每个像素所需的位数,必须是或 1,4,8 24(// 真彩色 ) 之一 (28-29 字节 ) //if(type!=0x0008)return;//非256色的BMP图,直接返回不处理。 //读出位图的宽度 ReadFileData(index,18,4,(u8 *)&width); //int image_width ; // 位图的宽度,以像素为单位 (18-21 字节 ) // printf("width=%u\r\n",width); //读出位图的高度 ReadFileData(index,22,4,(u8 *)&heigh); //int image_heigh ; // 位图的高度,以像素为单位 (22-25 字节 ) //printf("heigh=%u\r\n",heigh); if(width>LCD_WIDTH || heigh>LCD_HEIGHT)return;//超过LCD显示范围,不处理 //读位图数据起始地址 ReadFileData(index,10,4,(u8 *)&bfOffBits); //int bfOffBits ; // 位图数据的起始位置,以相对于位图 (10-13 字节 ) //以下读位图数据放到显示缓冲区 w=WidthBytes(24,width);//24位图 l=heigh-1;//BMP扫描顺序是:从下往上,从左往右扫描,因此先从最后一行开始读数据 LcdBlockWrite(x,y,x+width-1,y+heigh-1); for(i=0;ix2||y1>y2)return; if(x2>=LCD_WIDTH)x2=LCD_WIDTH-1; if(y2>=LCD_HEIGHT)y2=LCD_HEIGHT-1; w=x2-x1+1; h=y2-y1+1; LcdBlockWrite(x1,y1,x1+w-1,y1+h-1); for(j=0;j=LCD_WIDTH||y>=LCD_HEIGHT)return; if(x+width >=LCD_WIDTH)width=LCD_WIDTH-x-1; if(y+heigh >=LCD_HEIGHT)heigh=LCD_HEIGHT-y-1; LcdBlockWrite(x,y,x+width-1,y+heigh-1); for(j=0;jx2||y1>y2)return; if(x1>=LCD_WIDTH || y1>=LCD_HEIGHT)return; if(x2>=LCD_WIDTH)x2=LCD_WIDTH-1; if(y2>=LCD_HEIGHT)y2=LCD_HEIGHT-1; w=x2-x1+1; h=y2-y1+1; LcdBlockWrite(x1,y1,x1+w-1,y1+h-1); for(j=0;j(LCD_HEIGHT-1))y=LCD_HEIGHT-1; for(i=0;i(LCD_WIDTH-1))x=LCD_WIDTH-1; { //g_aucLcdBuf[y][x]=g_ucForeColorId; switch(colorIndex) { case COLOR_SELECT_BLUE:UpdateDot(g_ucSel_ColorId);break; case COLOR_WARN_RED:UpdateDot(g_ucWarnColorId);break; case COLOR_WHITE_BACK: UpdateDot(g_usBackColor);break; case COLOR_DEFAULT_BLUE: default:UpdateDot(g_ucForeColorId);break; } } } } //PaintBufToLcd(x1,y1,w,h); } #else /**************************************************************************** GuiFillRect 指定矩形区域填充前景色 ****************************************************************************/ void GuiFillRect(u16 x1, u16 y1, u16 x2, u16 y2) { u16 i,j,h,w; u16 x,y; if(x1>x2||y1>y2)return; if(x1>=LCD_WIDTH || y1>=LCD_HEIGHT)return; if(x2>=LCD_WIDTH)x2=LCD_WIDTH-1; if(y2>=LCD_HEIGHT)y2=LCD_HEIGHT-1; w=x2-x1+1; h=y2-y1+1; LcdBlockWrite(x1,y1,x1+w-1,y1+h-1); for(j=0;j(LCD_HEIGHT-1))y=LCD_HEIGHT-1; for(i=0;i(LCD_WIDTH-1))x=LCD_WIDTH-1; UpdateDot(g_ucForeColorId); } } //PaintBufToLcd(x1,y1,w,h); } #endif /**************************************************************************** GuiDrawHLine 画水平线 ****************************************************************************/ void GuiDrawHLine(u16 x1, u16 x2, u16 y, u8 width) { if(width==0)return; if(x2x2||y1>y2)return; GuiDrawHLine(x1,x2,y1,width); GuiDrawHLine(x1,x2,y2,width); GuiDrawVLine(y1,y2,x1,width,COLOR_DEFAULT_BLUE); GuiDrawVLine(y1,y2,x2,width,COLOR_DEFAULT_BLUE); } /*************************************************************************** 根据前景色和背景色的颜色索引g_ucForeColorId、g_ucBackColorId,从当前调色板中获取前景色和背景色g_usForeColor、g_usBackColor ****************************************************************************/ void UpdateColor(void) { u16 temp,r,g,b,RGB565; u8 R,G,B; //更新前景色 temp=g_ucForeColorId*4;//调色板每个索引对应4个字节,分别是BGRA (蓝、绿、红、透明度),目前A未用 B=g_Palette[temp]; G=g_Palette[temp+1]; R=g_Palette[temp+2]; r = R>>3; // 取R色的高5位 g = G>>2; // 取G色的高6位 b = B>>3; // 取B色的高5位 RGB565=((r<<11) + (g<<5) + (b<<0)); g_usForeColor=RGB565; //更新背景色 temp=g_ucBackColorId*4;//调色板每个索引对应4个字节,分别是BGRA (蓝、绿、红、透明度),目前A未用 B=g_Palette[temp]; G=g_Palette[temp+1]; R=g_Palette[temp+2]; r = R>>3; // 取R色的高5位 g = G>>2; // 取G色的高6位 b = B>>3; // 取B色的高5位 RGB565=((r<<11) + (g<<5) + (b<<0)); g_usBackColor=RGB565; //更新警告色 temp=g_ucWarnColorId*4;//调色板每个索引对应4个字节,分别是BGRA (蓝、绿、红、透明度),目前A未用 B=g_Palette[temp]; G=g_Palette[temp+1]; R=g_Palette[temp+2]; r = R>>3; // 取R色的高5位 g = G>>2; // 取G色的高6位 b = B>>3; // 取B色的高5位 RGB565=((r<<11) + (g<<5) + (b<<0)); g_usWarnColor=RGB565; } /**************************************************************************** GuiShowArrow 显示箭头,箭头尺寸16*16 ,左上角坐标x,y 模式mode: 高四位代表填充: 0x--非填充(只有边缘线条) 1x--填充 低四位代表方向:x1--向左 x2--向右 x3--向上 x4--向下 ****************************************************************************/ void GuiShowArrow(u16 x,u16 y,u16 len,u8 mode) { u16 i; u8 dir,fill; // if(x>=(LCD_WIDTH-len) || y>=(LCD_HEIGHT-len))return; dir=mode&0x0f; fill=mode&0xf0; switch(dir) { case 1: for(i = 0 ; i < len ; i ++){ GuiDrawRect(x+i,y-i,x+i,y+i,1); } break; case 2: for(i = 0 ; i < len ; i ++){ GuiDrawRect(x-i,y-i,x-i,y+i,1); } break; case 3: for(i = 0 ; i < len ; i ++){ GuiDrawRect(x-i,y+i,x+i,y+i,1); } break; case 4: for(i = 0 ; i < len ; i ++){ GuiDrawRect(x-i,y-i,x+i,y-i,1); } break; default: break; } } /************************************************************************ ShowButton 显示一个按钮 *************************************************************************/ void ShowButton(u16 x,u16 y,const char *str) { int len; len=GetStrXLen((char *)str); GuiClearRect(x,y,x+len+8,y+20); GuiShowStr(x+4,y+2,str,0x01,1); //GuiReverseRect(x,y,(x+len+8),(y+16+4)); } void ShowMessageBox(char *msg) { char buf[70]; u16 len,x,y; y=LCD_HEIGHT/2; GuiClearRect(0,y-20,LCD_WIDTH-1,y+20); GuiDrawRect(2,y-18,LCD_WIDTH-2,y+18,1); StrIntercept(buf,msg,18); len=GetStrXLen(buf); x=(LCD_WIDTH-len)/2; GuiShowStr(x,y-8,buf,0x01,0); } //注意调用此API前需要确定调用了 //LcdBlockWrite void UpdateDot(unsigned char colorID){ unsigned short RGB565; unsigned char R,G,B; unsigned short r,g,b; unsigned int temp; #if 1 temp=colorID*4; B=g_Palette[temp]; G=g_Palette[temp+1]; R=g_Palette[temp+2]; r = R>>3; // 取R色的高5位 g = G>>2; // 取G色的高6位 b = B>>3; // 取B色的高5位 RGB565=((r<<11) + (g<<5) + (b<<0)); LcdSendData(RGB565 >> 8); LcdSendData(RGB565 & 0xff); #else R=colorID; G=colorID++; B=colorID++; r = R>>3; // 取R色的高5位 g = G>>2; // 取G色的高6位 b = B>>3; // 取B色的高5位 RGB565=((r<<11) + (g<<5) + (b<<0)); LcdSendData(RGB565 >> 8); LcdSendData(RGB565 & 0xff); #endif } void lcdTestFlash(){ static char i; switch(i){ case 0:GuiClearAll();break; case 1:GuiShowStr(2,2,"hello world",1,0);break; case 2:GuiShowBmp(1,20,"speaker.bmp");break; case 3:GuiDrawRect(1,75, 41,85,1);break; case 4:GuiFillRect(1,87,41,100,COLOR_BLUE);break; case 5:GuiClearRect(1,87,41,100);break; case 6:GuiFillRect(1,87,41,100,COLOR_BLUE);break; case 7:GuiClearArea(1,87,41,14);break; case 8:GuiShowArrow(10,101,8,4);break; case 9:ShowButton(1,107,"菜单");break;//GuiShowStr(2,110,"reversed zone",1,1);break; default:break; } if(++i>15) i=0; } //stack init //typedef struct UI_STACK{ // char sta[4]; // char OK_back;//确认返回 // char top; // unsigned char FastUiChange;//快捷方式进入 //}UI_STACK; void Init_stack(struct UI_STACK* s) { memset(s->sta,0,sizeof(s->sta)); s->OK_back=0; s->top=-1; s->FastUiChange=0; } //push stack int PushUiStack(struct UI_STACK *s,int data) { if(s->top==4){ printf("stack full\r\n"); return 1; } (s->top)++; s->sta[s->top]=data; return 0; } //pull stack int PullUiStack(struct UI_STACK *s) { int tmp; if(s->top<0){ printf("stack is empty\r\n"); return -1; }else { tmp=(s->sta)[s->top]; (s->top)--; return tmp; } }