带有framebuffer的LCD读写的分层封装

本文介绍了如何在Linux系统中通过Framebuffer接口控制LCD设备,包括设备初始化、设置像素颜色、清屏以及显示内存中的颜色数据。主要涉及了文件操作、ioctl、mmap等系统调用。
摘要由CSDN通过智能技术生成


/*******************************************************************************
 * Copyleft (c) 2021 Kcode
 *
 * @file    fb.c
 * @brief   支持Framebuffer的LCD设备文件
 * @author  K
 * @version 0.0.1
 * @date    2021-07-02
 * @license MulanPSL-1.0
 *
 * 文件修改历史:
 * <时间>       | <版本>    | <作者>  | <描述>
 * 2021-07-02   | v0.0.1    | Kcode   | 支持Framebuffer的LCD设备文件
 * -----------------------------------------------------------------------------
 ******************************************************************************/

#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>

#include "debug_manager.h"

static int s_FBFD;
static int s_ScreenSize;
static int s_LineWidth;
static int s_PixelWidth;
static struct fb_var_screeninfo s_tVar;
static struct fb_fix_screeninfo s_tFix;
static unsigned char *s_pFbmem;

static int FBDeviceInit(void);
static int FBShowPixel(int PenX, int PenY, unsigned int Color);
static int FBCleanScreen(unsigned int BackColor);
static int FBShowPage(PT_PIXELDATAS pixel_datas);

static T_DispOpr s_tFBDispOpr = {
	.name         = "fb",
	.DeviceInit   = FBDeviceInit,
	.ShowPixel    = FBShowPixel,
	.CleanScreen  = FBCleanScreen,
	.ShowPage	  = FBShowPage,
};

/*!
 * @brief  "framebuffer显示设备"的初始化函数
 * @param  [in] 无
 * @return 0:注册成功,其他值:失败
 */
static int FBDeviceInit(void)
{
	/* 打开设备:支持读写 */
	s_FBFD = open(FB_DEVICE_NAME, O_RDWR);
	if (s_FBFD < 0) {
		DBG_PRINTF("can not open %s , err code :%d\n", FB_DEVICE_NAME, s_FBFD);
		return -1;
	}

	/* 获得可变信息 */
	if (ioctl(s_FBFD, FBIOGET_VSCREENINFO, &s_tVar)) {
		DBG_PRINTF("can not get s_tVar\n");
		return -1;
	}

	/* 获得固定信息 */
	if (ioctl(s_FBFD, FBIOGET_FSCREENINFO, &s_tFix)) {
		DBG_PRINTF("can not get s_tVar\n");
		return -1;
	}
	
	s_ScreenSize = s_tVar.xres * s_tVar.yres * s_tVar.bits_per_pixel / 8; // 屏幕总像素所占的字节数
	s_LineWidth   = s_tVar.xres * s_tVar.bits_per_pixel / 8;	// 每行像素所占的字节数
	s_PixelWidth  = s_tVar.bits_per_pixel / 8;	// 每个像素所占字节数

	/*存入信息(为了之后可能会用到)*/
	s_tFBDispOpr.Xres 		= s_tVar.xres; 
	s_tFBDispOpr.Yres 		= s_tVar.yres;
	s_tFBDispOpr.Bpp   		= s_tVar.bits_per_pixel;
	s_tFBDispOpr.LineWidth = s_LineWidth;
		
	/* 直接映射到内存的Framebuffer s_pFbmem为LCD buffer的基地址,往地址里面写东西 就可以改变颜色*/
	s_pFbmem = (unsigned char *)mmap(NULL, s_ScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, s_FBFD, 0);
	if (s_pFbmem == (unsigned char *)-1) {
		DBG_PRINTF("can not mmap\n");
		return -1;
	}
	s_tFBDispOpr.pDispMem = s_pFbmem;

	return 0;
}

/*!
 * @brief  设置FrameBuffer的指定像素点为某颜色
 * @param  PenX[in] 像素的x坐标
 * @param  PenY[in] 像素的y坐标
 * @param  Color[in] 颜色值,格式为32Bpp,即0x00RRGGBB
 * @return 0:成功,其他值:失败
 */
static int FBShowPixel(int PenX, int PenY, unsigned int Color)
{
	unsigned char  *pPen8;
	unsigned short *pPen16;
	unsigned int   *pPen32;
	unsigned int	red, green, blue;
	
	if ((PenX >= s_tVar.xres) || (PenY >= s_tVar.yres))
	{
		DBG_PRINTF("out of region\n");
		return -1;
	}

	/* 该坐标在内存中对应像素的位置 */
	pPen8  = s_pFbmem + PenY * s_LineWidth + PenX * s_PixelWidth;
	pPen16 = (unsigned short *)pPen8;
	pPen32 = (unsigned int   *)pPen8;

	switch (s_tFBDispOpr.Bpp) {
	case 8:
		*pPen8 = (unsigned char)Color;
		break;
	case 16:
		/* RGB:565 */
		red      = ((Color >> 16) & 0xff) >> 3;
		green    = ((Color >> 8 )  & 0xff) >> 2;
		blue     = ((Color >> 0 )  & 0xff) >> 3;
		*pPen16  = (red << 11) | (green << 5) | blue;
		break;
	case 32:
		*pPen32 = Color;
		break;
	default:
		DBG_PRINTF("can not surport %d bpp\n", s_tFBDispOpr.Bpp);
		return -1;
	}

	return 0;
}

/*!
 * @brief  "framebuffer显示设备"的清屏函数
 * @param  BackColor[in] 整个屏幕设置为该颜色
 * @return 0:成功,其他值:失败
 */
static int FBCleanScreen(unsigned int BackColor)
{
	int i;
	unsigned char  *pPen8;
	unsigned short *pPen16;
	unsigned int   *pPen32;
	unsigned int	red, green, blue;

	pPen8  = s_pFbmem;
	pPen16 = (unsigned short *)pPen8;
	pPen32 = (unsigned int   *)pPen8;

	switch (s_tFBDispOpr.Bpp) {
	case 8:
		memset(pPen8, BackColor, s_ScreenSize);
		break;
	case 16:
		/* RGB:565 */
		red      = ((BackColor >> 16) & 0xffff) >> 3;
		green    = ((BackColor >> 8 )  & 0xffff) >> 2;
		blue     = ((BackColor >> 0 )  & 0xffff) >> 3;
		BackColor = (red << 11) | (green << 5) | blue;
		/*循环写入像素点从而实现清屏*/
		for (i = 0; i < s_ScreenSize;) {    
			*pPen16 = BackColor;
			pPen16++;
			i += 2; //因为是16位的  ,所以要加2
		}
		break;
	case 32:
		/*循环写入像素点从而实现清屏*/
		for (i = 0; i < s_ScreenSize;) {
			*pPen32 = BackColor;
			pPen32++;
			i += 4;//因为是32位的  ,所以要加2
		}
		break;
	default:
		DBG_PRINTF("can not surport %dbpp\n", s_tFBDispOpr.Bpp);
		return -1;
	}

	return 0;
}

/*!
 * @brief  把PT_VideoMem中的颜色数据在FrameBuffer上显示出来
 * @param  pixel_datas[in] 内含整屏的象素数据
 * @return 0:成功,其他值:失败
 */
 static int FBShowPage(PT_PIXELDATAS pixel_datas)
{

    if (s_tFBDispOpr.pDispMem != pixel_datas->PixelDatas)
    {
	    memcpy(s_tFBDispOpr.pDispMem, pixel_datas->PixelDatas, pixel_datas->TotalBytes); 
    }
    
	return 0;
}
 
/*!
 * @brief  注册"framebuffer显示设备"
 * @param  [in] 无
 * @return 0:成功,其他值:失败
 */
int FBInit(void)
{
	return RegisterDispOpr(&s_tFBDispOpr);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值