📄 tft.c
字号:
putpixel(x, y, color);
x++;
k++;
if(k == 8)
{
Logo ++;
k = 0;
}
}
y++;
}
}
/*
在指定位置显示位图, 采用.dta的数据结构
src,为DTA数据的地址。
说明: 这里显示的图像仅支持一种格式,就是8位的332的图像格式, 这样就最大的解决编程时间。\
在图像格式是否合法方面也不做任何的判断
这里所处理的文件格式:
1. 这个驱动板的上的颜色字节由高到低时红绿蓝,但是bmpconvert的颜色字节由低到高的顺序是\
蓝绿红. 所以在转换的时候,采用的是8bit color233的模式,正好符合我们现在的红色占3位,\
绿色也占三位,不过在输出的字节顺序需要做一定的调整就行了。
2. 这里还有一个巧合,256色正好占一个字节,所以无论是多少乘以多少点阵的图像没有空闲的位。
3. 图像是采用横向取模的。
*/
/* This structure may not be changed because the data that it
expects is read in binary form (via any kind of interface,
at runtime).
This structure should therefor not be changed.
*/
typedef struct {
U16 ID; /* Version 1.00 => 100*/
U16 Version;
U16 XSize;
U16 YSize;
U16 BytesPerLine;
U16 BitsPerPixel;
U16 NumColors;
U16 HasTrans;
} GUI_BITMAP_STREAM;
void TFT_Lcd_Disp_Bitmap(GUI_BITMAP_STREAM *src, int x0, int y0)
{
byte *pdata;
word xsize;
word ysize;
word numcolors;
word i, j;
byte c, c_;
int x, y;
// 读取文件的头, 做相应的处理。
numcolors = src->NumColors;
pdata = ((byte*)src) + 16 + 4*numcolors;
xsize = src->XSize;
ysize = src->YSize/2; // 调试, 原始版本可以不用除以2
y = y0;
for (i = 0; i < ysize; i++)
{
x = x0;
for (j = 0; j < xsize; j++)
{
c_ = *pdata++;
c = (c_<<5) | ((c_&0x38)>>1) | (c_>>6);
putpixel(x, y, c);
x++;
}
y++;
}
}
void plot_circle_points(int xc, int yc, int x, int y, unsigned char c);
/*----------------------------------------------------------------------------*
* 描出一个字或字符
* 输入参数:
* qu: 汉字时, 为区码; ASCII字符时, 为0
* wei: 汉字时, 为位码; ASCII字符时, 为ASCII码
* size: 高4位为纵向扩展倍数, 低4位为横向扩展倍数
* font: 显示字体
* color: 字体颜色
* x0, y0: 字符位置
* 返回值: 显示一个字(或是字符)所需要的点阵宽度
* 可以优化的部分有:
* 如果当前显示字符为空格, 直接返回空格所占的宽度, 就不用描述后面的点了
*----------------------------------------------------------------------------*/
int Lcd_Draw_Char(byte qu, byte wei, byte size, byte font, byte color, int x0, int y0)
{
byte *dot_src; // 字库点阵首地址
word offset; //字符在字库中的相对位置
byte dot_buf[FONT_HOR_MAX*FONT_ELG_MAX/8]; // 开辟一个最大的行缓冲区.
word dot_dst_inc; // 打印一个字符时候的点长
byte src_inc; // 字库的行增量
byte hor_size, vrt_size;
byte i, j, k; // 循环变量
hor_size = size&0x0f;
vrt_size = size>>4;
dot_dst_inc = (word)Font_Size[font][0] * hor_size;/*取一个byte在TFT上所需要的点阵宽度*/
if(qu != 0) //如果是一个汉字, 需要2个byte 的宽度
dot_dst_inc *= 2;
else if(wei == 0x20)//如果判断该字符为空格, 直接返回空格所占的宽度
return dot_dst_inc;
src_inc = (Font_Size[font][2]+7)>>3; // 每一种字体所需的移动变量
offset = Font_Search_Offset(qu, wei);
dot_src = (byte *)&Font_Addr[font][(DWORD)offset*((Font_Size[font][2]+7)>>3)*(Font_Size[font][3])];
//Analy added for symbol display for ROLAY version 2006-09-12
if((!qu)&&(wei >= 0x80))//在显示特殊字符时, 需要取新的点阵地址, 目前只有9*17的点阵具有这些特殊字符的字库
Get_Font_Addr(wei, &((dword)dot_src));
//analy add end
for (i = 0; i < Font_Size[font][3]; i++) // 总共需要显示的行数,由于有些字库最后一行可能没有,这样就可以直接不用显示
{
memset(dot_buf, 0, FONT_HOR_MAX*FONT_ELG_MAX/8);
// 对点阵进行横向扩展
if (hor_size == 1) // 字体按照原始大小进行打印, 由于这种情况最多,所以为了节约时间,又单独进行了处理
{
memcpy(dot_buf, dot_src, src_inc);
dot_src += src_inc;
}
else // 字体有一定的扩展倍数
{
TFT_Font_Dot_ELg(dot_buf, dot_src, Font_Size[font][2], hor_size); // 把扩展后的目标点阵拷贝到点阵缓冲区中。
dot_src += src_inc;
}
// 把转换后的点阵显示出来, 纵向扩展等于把一列进行重复显示就行了。
for (j = 0; j < vrt_size; j++) // 重复显示的列数
{
for (k = 0; k < dot_dst_inc; k++)
{
if (dot_buf[k>>3]&and_table2[k&0x07])
putpixel(x0+k, y0, color);
}
y0++;
}
}
return dot_dst_inc;
}
// 画圆函数
void Lcd_Draw_Circle(int xc, int yc, int radius, unsigned char c)
{
int x, y, p;
x = 0;
y = radius;
p = 3-2 * radius;
while(x<y)
{
plot_circle_points(xc, yc, x, y, c);
if(p<0)
p=p+4*x+6;
else
{
p=p+4*(x-y)+10;
y-=1;
}
x+=1;
}
if(x==y)
plot_circle_points(xc, yc, x, y, c);
}
//--画8个象限的点
void plot_circle_points(int xc, int yc, int x, int y, unsigned char c)
{
putpixel(xc+x, yc+y, c);
putpixel(xc-x, yc+y, c);
putpixel(xc+x, yc-y, c);
putpixel(xc-x, yc-y, c);
putpixel(xc+y, yc+x, c);
putpixel(xc-y, yc+x, c);
putpixel(xc+y, yc-x, c);
putpixel(xc-y, yc-x, c);
}
// 画实心圆函数
void Lcd_Draw_Circle_Fill(int x0, int y0, int r, unsigned char c)
{
int i, x;
int sqmax = r*r+r/2;
int yMin, yMax;
/* First step : find uppermost and lowermost coordinates */
yMin = y0 - r;
yMax = y0 + r;
/* Use Clipping rect to reduce calculation (if possible) */
if (yMax >= LCD_Ydot)
yMax = LCD_Ydot-1;
if (yMin < 0)
yMin = 0;
/* Draw top half */
for (i=0, x=r; i<=r; i++) {
int y = y0-i;
if ((y >= yMin) && (y <= yMax)) {
/* calc proper x-value */
while ((i*i+x*x) >sqmax)
--x;
Lcd_Draw_HLine (x0-x, y, x0+x, c);
}
}
/* Draw bottom half */
for (i=1, x=r; i<=r; i++) {
int y = y0 + i;
if ((y >= yMin) && (y <= yMax)) {
/* calc proper x-value */
while ((i*i+x*x) >sqmax)
--x;
Lcd_Draw_HLine (x0-x, y, x0+x, c);
}
}
}
/*
画实心矩形函数
*/
void Lcd_Draw_Rect_Fill(int x1, int y1, int x2, int y2, unsigned char c)
{
if (y1 < y2)
{
while(y1 <= y2)
{
Lcd_Draw_HLine(x1, y1, x2, c);
y1++;
}
}
else // y1>=y2
{
while(y2 <= y1)
{
Lcd_Draw_HLine(x1, y2, x2, c);
y2++;
}
}
}
/*******************************************************************************
画空心矩形函数
*******************************************************************************/
void Lcd_Draw_Rect_EMP(int x1, int y1, int x2, int y2, unsigned char c)
{
Lcd_Draw_HLine(x1, y1, x2, c);
Lcd_Draw_HLine(x1, y2, x2, c);
Lcd_Draw_VLine(x1, y1, y2, c);
Lcd_Draw_VLine(x2, y1, y2, c);
}
// ---画任意直线
void Lcd_Draw_Line(int x1,int y1,int x2,int y2, unsigned char c)
{
int dx,dy,tmp,di,const1,const2,inc;
dx=x2-x1;
dy=y2-y1;
inc=1;
if (abs(dx)>abs(dy))
{
if (dx<0)
{
tmp=x1;
x1=x2;
x2=tmp;
tmp=y1;
y1=y2;
y2=tmp;
dx=-dx;
dy=-dy;
}
if(dy<0)
{
dy=-dy;
inc=-1;
}
di=2*dy-dx;
const1=2*dy-2*dx;
const2=2*dy;
putpixel(x1,y1,c);
while (x1<x2)
{
x1=x1+1;
if (di>=0)
{
y1=y1+inc;
di=di+const1;
}
else
di=di+const2;
putpixel(x1,y1,c);
}
}
else
{
if (dy<0)
{
tmp=x1;
x1=x2;
x2=tmp;
tmp=y1;
y1=y2;
y2=tmp;
dx=-dx;
dy=-dy;
}
if (dx<0)
{
inc=-1;
dx=-dx;
}
di=dy-2*dx;
const1=-2*dx;
const2=2*dy-2*dx;
putpixel(x1,y1,c);
while (y1<y2)
{
y1=y1+1;
if (di>=0)
di=di+const1;
else
{
x1=x1+inc;
di=di+const2;
}
putpixel(x1,y1,c);
}
}
}
/*
写一个像素点到屏上,带颜色
*/
extern const DWORD Lcd_Row_Addr[LCD_Ydot];
void Lcd_Draw_Pixel(int x, int y, byte color)
{
static byte a16;
static unsigned long p;
// p = (unsigned long)y*SCREEN_WIDE+(unsigned long)x;
if ((unsigned)y >= LCD_Ydot || (unsigned)x >= LCD_Xdot)
return;
p = Lcd_Row_Addr[y] + x;
a16 = (byte)(p>>16);
a16 <<= 2;
TFT_WrCmd(0x00|a16 );
TFT_WrDat((byte)p);
TFT_WrCmd(0x01|a16);
TFT_WrDat((byte)(p>>8));
TFT_WrCmd(0x02|a16);
TFT_WrDat(color);
}
/*
*********************************************************
* *
* LCD_DrawLine vertical/horizontal *
* *
*********************************************************
*/
void Lcd_Draw_HLine(int x0, int y, int x1, byte c)
{
static byte a16;
static unsigned long p;
#if 1 // 这两段是不同的实现语句
if ((unsigned)y >= LCD_Ydot)
return;
if (x0 < x1)
{
if (x0 >= LCD_Xdot || x1 < 0)
return;
if (x1 >= LCD_Xdot)
x1 = LCD_Xdot;
if (x0 < 0)
x0 = 0;
p = Lcd_Row_Addr[y] + x0;
a16 = (byte)(p>>16);
a16 <<= 2;
TFT_WrCmd(0x00|a16 );
TFT_WrDat((byte)p);
TFT_WrCmd(0x01|a16);
TFT_WrDat((byte)(p>>8));
TFT_WrCmd(0x02|a16);
while(x0 <= x1)
{
TFT_WrDat(c);
x0++;
}
}
else // x1 < x0
{
if (x1 >= LCD_Xdot || x0 < 0)
return;
if (x0 >= LCD_Xdot)
x0 = LCD_Xdot;
if (x1 < 0)
x1 = 0;
p = Lcd_Row_Addr[y] + x1;
a16 = (byte)(p>>16);
a16 <<= 2;
TFT_WrCmd(0x00|a16 );
TFT_WrDat((byte)p);
TFT_WrCmd(0x01|a16);
TFT_WrDat((byte)(p>>8));
TFT_WrCmd(0x02|a16);
while(x1 <= x0)
{
TFT_WrDat(c);
x1++;
}
}
#else
Lcd_Draw_Line(x0, y, x1, y, c);
#endif
}
/* Following for test the TFT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -