?? lcd.c
字號(hào):
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
/*#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
*/#include <string.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <termios.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include "lcd.h"
#include "ascii.c"
struct termios save;
int current_vt;
int con;
FILE *fp =NULL;
/* LCD screen routine for M68VZ328 */
unsigned char *lcd_base = 0;
unsigned char curFontColor=0x1f;
unsigned char curBackColor=0x0;
/*
* 清空FB內(nèi)容
*/
void cls(void)
{
int i;
memset(lcd_base , curBackColor , SCREEN_WIDTH * SCREEN_HEIGHT);
}
/*
* FB的初始化:獲取fb_var_screeninfo、fb_fix_screeninfo、
* 字庫等信息,并將FB映射到內(nèi)存。
*/
int fb_init()
{
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
struct termios current;
tcgetattr(0, &save);
current = save;
current.c_lflag &= ~ICANON;
current.c_lflag &= ~ECHO;
current.c_cc[VMIN] = 1;
current.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, ¤t);
current_vt = open("/dev/tty", O_RDWR);
ioctl(current_vt, KDSETMODE, KD_GRAPHICS);
//打開設(shè)備文件FB,用文件描述詞con指向它
con = open("/dev/fb0", O_RDWR, 0);
if (con < 0) {
fprintf(stderr, "Can't open /dev/fb0\n");
return 0;
}//設(shè)備文件未打開,返回
if ( ioctl(con, FBIOGET_FSCREENINFO, &finfo) < 0 ) {
fprintf(stderr, "Can't get FSCREENINFO\n");
close(con);
return 0;
}//獲取fb_fix_screeninfo信息失敗,返回
if ( ioctl(con, FBIOGET_VSCREENINFO, &vinfo) < 0 ) {
fprintf(stderr, "Can't get VSCREENINFO\n");
close(con);
return 0;
}//獲取fb_var_screeninfo信息失敗,返回
if (vinfo.bits_per_pixel != 8) {
vinfo.bits_per_pixel = 8;
ioctl(con, FBIOPUT_VSCREENINFO, &vinfo);
}//修正像素所占的字節(jié)數(shù)
//將FB映射到內(nèi)存中,并用lcd_base返回該內(nèi)存的起始位置
lcd_base = mmap(NULL, SCREEN_WIDTH * SCREEN_HEIGHT , PROT_READ|PROT_WRITE, MAP_SHARED, con, 0);
if ( lcd_base == MAP_FAILED )
{
fprintf(stderr, "Can't mmap\n");
close(con);
return 0;
}//映射失敗,返回
printf("Video memory address = 0x%x\n",lcd_base);
cls();
//以只讀形式打開二進(jìn)制文件FONT_FILE(字庫)
fp = fopen(FONT_FILE, "rb");
if(!fp){
printf("Open hzk failed!\n");
close(con);
return 0;
}//文件打開失敗,返回
return -1;
}
/*
* 釋放FB所占內(nèi)存,關(guān)閉字庫
*/
void fb_release(void)
{
munmap(lcd_base,FB_SIZE);
if(fp)
fclose(fp);
if(con)
close(con);
}
//////////////////
/* 設(shè)置字體顏色 */
int SetFrontColor(unsigned char clr)
{
curFontColor = clr;
}
/* 設(shè)置背景顏色 */
int SetBackColor(unsigned char clr)
{
curBackColor = clr;
}
/* 一屏的數(shù)據(jù)容量(以字節(jié)計(jì)) */
int SysBytesPerScreen()
{
return (SCREEN_WIDTH*SCREEN_HEIGHT*BPP/8);
}
/* 獲取FB映射的內(nèi)存的起始地址 */
int lcd_getdisplay()
{
return (int)lcd_base;
}
/* 獲取屏幕一行的像素?cái)?shù) */
int lcd_getx()
{
return SCREEN_WIDTH;
}
/* 獲取屏幕一列的像素?cái)?shù) */
int lcd_gety()
{
return SCREEN_HEIGHT;
}
/* 為fbuf指向的區(qū)域中點(diǎn)(x,y)賦值color */
int _lcd_putpixel(
char *fbuf,
int x,
int y,
unsigned char color,
int xorm
)
{
unsigned char *p;
//找到點(diǎn)(x,y)在區(qū)域中對(duì)應(yīng)的位置
p = fbuf + y * SCREEN_WIDTH * BPP / 8 + x ;
*p = curFontColor;
return 0;
}
/* 設(shè)置屏幕上點(diǎn)(x,y)值為c */
int lcd_putpixel(short x, short y, unsigned char c, int xorm)
{
return _lcd_putpixel(
lcd_base,
x,
y,
c,
xorm
);
}
/* 獲取fbuf指向的區(qū)域中點(diǎn)(x,y)的值 */
char _lcd_getpixel(
unsigned char *fbuf,
int x,
int y
)
{
unsigned char *p;
p = fbuf + y * LINE_OFFSET + x;
return (*p);
}
/* 獲取屏幕上點(diǎn)(x,y)的值 */
char lcd_getpixel(
short x,
short y
)
{
return _lcd_getpixel(
lcd_base,
x,
y
);
}
/* quick method for hline */
/*
* 從(x1,y)到(x2,y)畫水平線,fbuf指向FB
*/
int _lcd_hline(unsigned char *fbuf, short x1, short y, short x2, unsigned char color, int xorm)
{
unsigned long startOffset;
//找到水平線的起點(diǎn)
startOffset = (y * LINE_OFFSET + x1) ;
//設(shè)置水平線涉及的各個(gè)像素點(diǎn)的值
memset((char*)((unsigned long)lcd_base + (unsigned long)startOffset), color, (x2 - x1) );
return 0;
}
/* 在屏幕上畫出水平線,從(x1,y)到(x2,y) */
int lcd_hline(
short x1,
short y,
short x2,
unsigned char c,
int xorm
)
{
return _lcd_hline(
(void *)lcd_base,
x1,
y,
x2,
c,
xorm
);
}
/*
* 從(x,y1)到(x,y2)畫豎線,fbuf指向FB
*/
int _lcd_vline(
unsigned char *fbuf,
int x,
int y1,
int y2,
unsigned char color,
int xorm
)
{
int startOffset, endOffset , i ;
char *point;
//豎線的起點(diǎn)
startOffset = (y1 * LINE_OFFSET + x) ;
//豎線的終點(diǎn)
endOffset = (unsigned long)lcd_base + (unsigned long)startOffset + (y2 - y1) * LINE_OFFSET ;
//設(shè)置豎線涉及的各個(gè)像素點(diǎn)的值
for (i = (unsigned long)lcd_base + (unsigned long)startOffset; i <= endOffset; i += LINE_OFFSET ) {
*(point=(char*)i) =color;
}
return 0;
}
/* 在屏幕上畫出豎線,從(x,y1)到(x,y2) */
int lcd_vline(
short x,
short y1,
short y2,
unsigned char c,
int xorm
)
{
return _lcd_vline(
(void *)lcd_base,
x,
y1,
y2,
c,
xorm
);
}
/*
* 在水平投影大于垂直投影時(shí),畫斜線,
* 起始點(diǎn)為(x,y),水平投影為dx,垂直投影為dy
* dir=1時(shí)由左向右畫,dir=-1時(shí)反之
*/
static inline void draw_xish_line(short x, short y, short dx, short dy, short xdir,int color)
{
short dyX2=dy+dy;
short dyX2mdxX2=dyX2-(dx+dx);
short error=dyX2-dx;
//設(shè)置起始點(diǎn)的值
lcd_putpixel(x, y, color, 0);
//設(shè)置斜線上各點(diǎn)的值
while (dx--) {
if (error >= 0) {
y++;
error += dyX2mdxX2;
} else {
error += dyX2;
}
x += xdir;//找到斜線上的下一個(gè)點(diǎn)
lcd_putpixel(x,y,color,0);
}
}
/*
* 在水平投影小于垂直投影時(shí),畫斜線,
* 起始點(diǎn)為(x,y),水平投影為dx,垂直投影為dy
* dir=1時(shí)由上向下畫,dir=-1時(shí)反之
*/
static inline void draw_yish_line(short x, short y, short dx, short dy,short xdir,int color)
{
short dxX2=dx + dx;
short dxX2mdyX2=dxX2-(dy+dy);
short error=dxX2-dy;
//設(shè)置起始點(diǎn)的值
lcd_putpixel(x, y, color, 0);
//設(shè)置斜線上的各個(gè)值
while (dy--) {
if (error >= 0) {
x+= xdir;//找到斜線上的下一個(gè)點(diǎn)
error += dxX2mdyX2;
} else {
error += dxX2;
}
y++;
lcd_putpixel(x,y, color, 0);
}
}
/*
* 在屏幕上畫出(x1,y1)到(x2,y2)的連線
*/
void lcd_line(short x1, short y1, short x2, short y2,int color)
{
short dx,dy;
if ( y1 > y2) {
short t = y1;
y1 = y2;
y2 = t;
t = x1;
x1 = x2;
x2 = t;
}//保證起點(diǎn)在終點(diǎn)的下方
dx = x2-x1;
dy = y2-y1;
if (dx > 0) {
//起點(diǎn)在終點(diǎn)的左邊
if (dx > dy)
draw_xish_line(x1, y1, dx, dy, 1,color);
else
draw_yish_line(x1, y1, dx, dy, 1,color);
} else {
//起點(diǎn)在終點(diǎn)的右邊
dx = -dx;
if (dx > dy)
draw_xish_line(x1, y1, dx, dy, -1,color);
else
draw_yish_line(x1, y1, dx, dy, -1,color);
}
}
/*
* 用逐列掃描的方式繪出一個(gè)矩形
* (x,y),(x1,y1)分別為矩形的對(duì)角線的兩端點(diǎn)
*/
int _lcd_fillrect(
unsigned char *fbuf,
int x,
int y,
int x1,
int y1,
int color
)
{
int tmp, w, h;
if (x1 < x){
tmp = x;
x = x1;
x1 = tmp;
}//保證(x,y)在(x1,y1)左邊
if (y1 < y){
tmp = y;
y = y1;
y1 = tmp;
}//保證(x,y)在(x1,y1)下邊
w = x1 - x + 1;
h = y1 - y + 1;
//逐列畫豎線
for (h += y; y < h; y++) {
lcd_hline(x,y,x1,color,0);
}
return 0;
}
/*
* 在屏幕上繪出矩形
*/
int lcd_fillrect(short x1, short y1, short x2, short y2, int c)
{
return _lcd_fillrect(
(unsigned char *)lcd_base,
x1,
y1,
x2,
y2,
c
);
}
/*
* 將buf指向的文本顯示到屏幕上(x,y)開始的位置
*/
int lcd_textout(short x, short y, unsigned char* buf,int color)
{
unsigned char CH, CL;
int Pos;
char pixel[256];//存放顯示到屏幕上的每個(gè)字符的信息16*16B
char pData[32];//存放顯示字符的各個(gè)點(diǎn)的亮滅16*16/2=32B
char* pBuf=NULL;
int i=0,j=0;
unsigned short mask=0x8000;//對(duì)各個(gè)像素進(jìn)行分析
short *pVal;
int offset =0,val;
pVal = (short *)buf;
//逐字符讀入
while (*buf)
{
//初始化pixel,設(shè)置底色,為顯示字符做準(zhǔn)備
memset(pixel, curBackColor, sizeof(unsigned char)*sizeof(pixel));
CH = buf[0];
CL = buf[1];
if (CH >= 0xA0 && CH < 0xF8 && CL >= 0xA0 && CL < 0xFF)
{
//按區(qū)位號(hào)找到漢字的位置
Pos = ((CH - 0xA1) * 94 + (CL - 0xA1)) * 32;
fseek(fp, Pos, SEEK_SET);
//將該漢字存入pBuf中
pBuf = pData;
fread(pBuf, 32, 1, fp);
offset = 2;
}//字符為漢字
else
{
pBuf = (char*)(FontLib[CH]);
offset = 1;
}//字符為ascii碼
for(i=0; i<16; i++)
{
//將每個(gè)顯示在屏幕上的字符第i行像素亮滅信息(16bits)存入val中
val = (pBuf[2*i]<<8) | (pBuf[2*i+1]);
for(j=0;j<16;j++)
{
//當(dāng)像素點(diǎn)有信息要顯示,即與屏幕底色不同時(shí),
//更改該像素的顏色為設(shè)定值color
if( val & (mask>>j) )
{
pixel[i*16+j] = color;
}
}//對(duì)每行中的每個(gè)像素進(jìn)行分析
}//逐行分析
//將pixel的內(nèi)容顯示到屏幕上
lcd_bitmap(x, y, 16, 16, pixel, 0);
x += 16;
buf += offset;//對(duì)下一個(gè)漢字或ascii碼進(jìn)行操作
}
return 1;
}
/*
* 在屏幕上用相鄰的4個(gè)像素組成的正方形表示一個(gè)“大像素點(diǎn)”
*/
static int lcd_putbigpixel(short x, short y, unsigned char c, int xorm){
// lcd_putpixel(x, y, c, xorm); lcd_fillrect(x, y, x+1, y+1, c);
}
/*
* 以(x,y)為中心、以a為半橫軸、b為半縱軸在屏幕上畫橢圓
*/
int lcd_ellipse(
short x,
short y,
short a,
short b,
unsigned char c,
int xorm
)
{
int wx, wy;
int thresh;
int asq = a * a;
int bsq = b * b;
int xa, ya;
//畫出縱軸兩個(gè)端點(diǎn)#if 1 lcd_putbigpixel(x, y+b, c, xorm);
lcd_putbigpixel(x, y-b, c, xorm);
#endif
wx = 0;
wy = b;
xa = 0;
ya = asq * 2 * b;
thresh = asq / 4 - asq * b;
//畫出橢圓中旋轉(zhuǎn)角在45~90、245~270的部分
for (;;) {
thresh += xa + bsq;
if (thresh >= 0) {
ya -= asq * 2;
thresh -= ya;
wy--;
}
xa += bsq * 2;
wx++;
if (xa >= ya)
break;
#if 1 lcd_putbigpixel(x+wx, y-wy, c, xorm);
lcd_putbigpixel(x-wx, y-wy, c, xorm);
lcd_putbigpixel(x+wx, y+wy, c, xorm);
lcd_putbigpixel(x-wx, y+wy, c, xorm);
#endif }
//畫出橫軸兩個(gè)端點(diǎn)#if 1 lcd_putbigpixel(x+a, y, c, xorm);
lcd_putbigpixel(x-a, y, c, xorm);
#endif
wx = a;
wy = 0;
xa = (bsq * a) << 1;
ya = 0;
thresh = (bsq >> 2) - bsq * a;
//畫出橢圓中旋轉(zhuǎn)角在-45~45、135~245的部分
for (;;) {
thresh += ya + asq;
if (thresh >= 0) {
xa -= bsq + bsq;
thresh = thresh - xa;
wx--;
}
ya += asq + asq;
wy++;
if (ya > xa)
break;
#if 1 lcd_putbigpixel(x+wx, y-wy, c, xorm);
lcd_putbigpixel(x-wx, y-wy, c, xorm);
lcd_putbigpixel(x+wx, y+wy, c, xorm);
lcd_putbigpixel(x-wx, y+wy, c, xorm);
#endif }
}
/*
* 將bitmap指向的區(qū)域內(nèi)容保存至FB中(x,y)開始的、長width、寬height區(qū)域
*/
int _lcd_bitmap(
void *fbuf,
int x,
int y,
int width,
int height,
unsigned char *bitmap,
int xorm
)
{
unsigned char *dst;
unsigned char *src;
int width_bytes;
int xi, yi;
//在FB中找到(x,y)點(diǎn)對(duì)應(yīng)的信息
dst = fbuf + y * LINE_OFFSET + x ;
width_bytes = width;
src = bitmap;
/* speedcode */
for (yi = 0; yi < height; yi++) {
for (xi = 0; xi < width_bytes; xi++) {
dst[xi] = *src++;
}//掃描一行信息
dst += LINE_OFFSET;
}//逐行掃描信息
return 0;
}
/*
* 將ppc指向的區(qū)域內(nèi)容顯示到屏幕上(x0,y0)開始的、長width、寬height區(qū)域
*/
int lcd_bitmap(
short x0,
short y0,
short width,
short height,
unsigned char *pcc,
int xorm
)
{
return _lcd_bitmap(
lcd_base,
x0,
y0,
width,
height,
pcc,
xorm
);
}
/*
* 顯示屏幕色彩
*/
void show_palette()
{
int i , j ;
//在屏幕開頭顯示文本:system palette
lcd_textout(0,0,"system palette",0x3f);
i=50000;
while(i--);
//將256種顏色以20*13的顏色塊分別顯示
for(i=0;i<16;i++)
{
for(j=0;j<16;j++)
{
SetFrontColor(i*16+j);
lcd_fillrect(j*20,i*13,(j+1)*20,(i+1)*13,0);
}
}
SetFrontColor(0x0);
SetFrontColor(0x15);
SetBackColor(0x9);
//輸出文本
lcd_textout(110,190,"系統(tǒng)調(diào)色板",0x4f);
lcd_textout(50,220,"linux palette!",0x5f);
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -