jz2440电子书(二)显示层

本文章以韦东山三期项目实战为基础,进行学习笔记和总结,所用源码出自教程,加上一些自己理解的注释


首先编写fb.c
定义一个opriation结构体

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); //打开fb设备
	if (0 > g_fd)
	{
		DBG_PRINTF("can't open %s\n", FB_DEVICE_NAME);
	}

	ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar); //调用ioctl获取可变参数
	if (ret < 0)
	{
		DBG_PRINTF("can't get fb's var\n");
		return -1;
	}

	ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);//调用ioctl获取固定参数
	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;			//设置定义的结构体的可变参数的X坐标
	g_tFBOpr.iYres       = g_tFBVar.yres;			//设置定义的结构体的可变参数的Y坐标
	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; //保留5位
			iGreen 		= (dwColor >> (8+2)) & 0x3f;   //保留6位
			iBlue  		= (dwColor >> 3) & 0x1f;	   //保留5位
			wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue; //新的16位像素
			*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;
}

fbinit用于向上层注册

int FBInit(void)
{
	return RegisterDispOpr(&g_tFBOpr); //向上层注册fb_operation
}

上面就完成了fb.c文件的编写,如果有其他显示设备以此为框架进行模仿,最后向上层注册就可以。


上层的disp.manager.c文件
首先在dis_manager.h 定义一个结构体

typedef struct DispOpr {
	char *name;		//名字
	int iXres;		//X坐标
	int iYres;		//Y坐标
	int iBpp;		//每个像素用多个位表示
	int (*DeviceInit)(void);	//设备初始化
	int (*ShowPixel)(int iPenX, int iPenY, unsigned int dwColor);//显示一个像素
	int (*CleanScreen)(unsigned int dwBackColor); //清除屏幕
	struct DispOpr *ptNext;
	}T_DispOpr, *PT_DispOpr;

当mian.c中调用需要显示初始化时

int DisplayInit(void)
{
	int iError;
	
	iError = FBInit();

	return iError;
}

从上边这个初始化函数就能走到刚才的fb.c的init函数,从而在注册结构体并写进disp链表里。

int RegisterDispOpr(PT_DispOpr ptDispOpr)
{
	PT_DispOpr ptTmp;

	if (!g_ptDispOprHead) //如果链表头为空
	{
		g_ptDispOprHead   = ptDispOpr;  //链表头等于传入的结构体
		ptDispOpr->ptNext = NULL;		//下一项为空
	}
	else
	{
		ptTmp = g_ptDispOprHead; //定义的结构体位链表头
		while (ptTmp->ptNext)    //如果结构体的下一项不为空
		{
			ptTmp = ptTmp->ptNext; //就走到下一个结构体
		}
		ptTmp->ptNext	  = ptDispOpr; //把传入的结构体写入链表
		ptDispOpr->ptNext = NULL; //新的链表的下一项为空
	}

	return 0;
}

显示的一块的差不多就是这样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一叶舞澎湃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值