Chinaunix首页 | 论坛 | 博客
  • 博客访问: 301016
  • 博文数量: 76
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 715
  • 用 户 组: 普通用户
  • 注册时间: 2015-05-20 20:38
文章分类
文章存档

2016年(20)

2015年(56)

分类: 嵌入式

2015-08-23 16:44:40

fb.c

15年8月22日14:27:31

#include <config.h>

#include <disp_manager.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/ioctl.h>

#include <sys/mman.h>

#include <linux/fb.h>

#include <string.h>


static int FBDeviceInit(void);

static int FBShowPixel(int iX, int iY, unsigned int dwColor);

static int FBCleanScreen(unsigned int dwBackColor);


static int g_fd;


static struct fb_var_screeninfo g_tFBVar;

static struct fb_fix_screeninfo g_tFBFix;

static unsigned char *g_pucFBMem;

static unsigned int g_dwScreenSize;


static unsigned int g_dwLineWidth;

static unsigned int g_dwPixelWidth;


static T_DispOpr g_tFBOpr = {

.name = "fb",

.DeviceInit = FBDeviceInit,

.ShowPixel = FBShowPixel,

.CleanScreen = FBCleanScreen,

};


static int FBDeviceInit(void)

{

int ret;

g_fd = open(FB_DEVICE_NAME, O_RDWR);

if (0 > g_fd)

{

DBG_PRINTF("can't open %s\n", FB_DEVICE_NAME);

}


ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar);

if (ret < 0)

{

DBG_PRINTF("can't get fb's var\n");

return -1;

}


ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);

if (ret < 0)

{

DBG_PRINTF("can't get fb's fix\n");

return -1;

}

g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8;

g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);

if (0 > g_pucFBMem)

{

DBG_PRINTF("can't mmap\n");

return -1;

}


g_tFBOpr.iXres = g_tFBVar.xres;

g_tFBOpr.iYres = g_tFBVar.yres;

g_tFBOpr.iBpp = g_tFBVar.bits_per_pixel;


g_dwLineWidth = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;

g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;

return 0;

}



static int FBShowPixel(int iX, int iY, unsigned int dwColor)

{

unsigned char *pucFB;

unsigned short *pwFB16bpp;

unsigned int *pdwFB32bpp;

unsigned short wColor16bpp; /* 565 */

int iRed;

int iGreen;

int iBlue;


if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres))

{

DBG_PRINTF("out of region\n");

return -1;

}


pucFB = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;

pwFB16bpp = (unsigned short *)pucFB;

pdwFB32bpp = (unsigned int *)pucFB;

switch (g_tFBVar.bits_per_pixel)

{

case 8:

{

*pucFB = (unsigned char)dwColor;

break;

}

case 16:

{

iRed = (dwColor >> (16+3)) & 0x1f;

iGreen = (dwColor >> (8+2)) & 0x3f;

iBlue = (dwColor >> 3) & 0x1f;

wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;

*pwFB16bpp = wColor16bpp;

break;

}

case 32:

{

*pdwFB32bpp = dwColor;

break;

}

default :

{

DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);

return -1;

}

}


return 0;

}


static int FBCleanScreen(unsigned int dwBackColor)

{

unsigned char *pucFB;

unsigned short *pwFB16bpp;

unsigned int *pdwFB32bpp;

unsigned short wColor16bpp; /* 565 */

int iRed;

int iGreen;

int iBlue;

int i = 0;


pucFB = g_pucFBMem;

pwFB16bpp = (unsigned short *)pucFB;

pdwFB32bpp = (unsigned int *)pucFB;


switch (g_tFBVar.bits_per_pixel)

{

case 8:

{

memset(g_pucFBMem, dwBackColor, g_dwScreenSize);

break;

}

case 16:

{

iRed = (dwBackColor >> (16+3)) & 0x1f;

iGreen = (dwBackColor >> (8+2)) & 0x3f;

iBlue = (dwBackColor >> 3) & 0x1f;

wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;

while (i < g_dwScreenSize)

{

*pwFB16bpp = wColor16bpp;

pwFB16bpp++;

i += 2;

}

break;

}

case 32:

{

while (i < g_dwScreenSize)

{

*pdwFB32bpp = dwBackColor;

pdwFB32bpp++;

i += 4;

}

break;

}

default :

{

DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);

return -1;

}

}


return 0;

}


int FBInit(void)

{

return RegisterDispOpr(&g_tFBOpr);

}


下面来分析这个文件:

1)设备初始化函数:当main函数选择对应的显示器后,需要调用这个函数进行显示器的初始化。

static int FBDeviceInit(void)

{

int ret;

/* 打开设备 */

g_fd = open(FB_DEVICE_NAME, O_RDWR);

if (0 > g_fd)

{

DBG_PRINTF("can't open %s\n", FB_DEVICE_NAME);

}

/* 获取所打开设备的一些文件信息 */

ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar); /* 可变参数信息 */

if (ret < 0)

{

DBG_PRINTF("can't get fb's var\n");

return -1;

}


ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix); /* 固定参数信息 */

if (ret < 0)

{

DBG_PRINTF("can't get fb's fix\n");

return -1;

}

g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8;

/* 屏幕大小根据刚才获取的信息可以计算出来, g_dwScreenSize的单位是byte */


g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);

if (0 > g_pucFBMem)

{

DBG_PRINTF("can't mmap\n");

return -1;

}

/* 映射到内存中,这样就可以想操作数组一样来操作了,比较方便 */


g_tFBOpr.iXres = g_tFBVar.xres;

g_tFBOpr.iYres = g_tFBVar.yres;

g_tFBOpr.iBpp = g_tFBVar.bits_per_pixel;

/* 将获取到的信息,填充 g_tFBOpr结构体。 */


g_dwLineWidth = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;

g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;

/* 计算一行的宽度和像素宽度,在后面的显示函数中将要使用,会在多个函数中使用,在初始化函 * 数中设置,方便以后使用。

*/

return 0;

}


函数返回值: 成功 --- 0


2)显示像素函数:

static int FBShowPixel(int iX, int iY, unsigned int dwColor)

{

unsigned char *pucFB;

unsigned short *pwFB16bpp;

unsigned int *pdwFB32bpp;

unsigned short wColor16bpp; /* 565 */

int iRed;

int iGreen;

int iBlue;


if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres))

{

DBG_PRINTF("out of region\n");

return -1;

}

/* 超出屏幕范围了 */


pucFB = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;


/* pucFB就是指向内存的一个指针,在2440LCD控制器直接从内存中取值显示在LCD上面,如 * 果想要在屏幕的(x,y)处显示红色,就要在(x,y)所对应的内存处写入红色。 g_pucFBMem是指 * 向映射后内存初始值的一个指针,想要算出任意点(x,y)在内存中的位置,需要在内存初始值的 * 基础上,加上一行的位宽乘以y,再加上像素宽度乘以x,即是这个式子。

*/


pwFB16bpp = (unsigned short *)pucFB;

pdwFB32bpp = (unsigned int *)pucFB;

switch (g_tFBVar.bits_per_pixel)

{

case 8:

{

*pucFB = (unsigned char)dwColor;

break;

/* 8bpp的时候,需要用到调色板了,直接这样设置就好 */

}

case 16:

{

iRed = (dwColor >> (16+3)) & 0x1f;

iGreen = (dwColor >> (8+2)) & 0x3f;

iBlue = (dwColor >> 3) & 0x1f;

wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;

*pwFB16bpp = wColor16bpp;

break;

}


/* 这个函数传入的颜色参数dwColor是这样表示的0x00RRGGBB,需要将他们转 * 换成RGB565的格式。如果这个不好理解的话,可以看下面的:

* iRed = (dwColor >> 16) & 0xff;

* iGreen = (dwColor >> 8) & 0xff;

* iBlue = (dwColor >> 0) & 0xff;

* wColor16bpp = (((iRed >> 3) << 11) | ((iGreen >> 2) << 5) | * (iBlue >> 3));

* *pwFB16bpp = wColor16bpp;

*/


case 32:

{

*pdwFB32bpp = dwColor;

break;

}

default :

{

DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);

return -1;

}

}


return 0;

}

函数返回值: 成功 --- 0


3)清屏函数:跟上面的函数很相似。就不再详细解释了。

4FBInit函数:只是给display_manager.c提供一个接口,用于将 g_tFBOpr结构体添加进链表里面。

int FBInit(void)

{

return RegisterDispOpr(&g_tFBOpr);

}



阅读(1648) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~