linux应用项目(一)数码相框(3)数码相框之电子书
来源:互联网 发布:语文名师讲课软件 编辑:程序博客网 时间:2024/06/11 02:34
一、整体思路
这一节我们重点学习框架,就是编程的思想。架构很重要。采用分层的思想,面向对象的编程思想。
1、怎样在LCD上显示一个文件
2、如何组织代码
分层的结构
main--draw--XXX_manager--fb.c等
二、分层编写-底层实现
1、显示部分代码编写
show_file\display\fb.cshow_file\display\disp_manager.cshow_file\include\config.hshow_file\include\disp_manager.hshow_file\draw\draw.c
先写fb.c 一面向对象编程思想
设置构造一个结构体
结构体需要有哪些成员呢:
显示部分,一定有一个显示函数,FB要显示就要初始化,所以有一个fb初始化函数,换页的时候我们要进行清屏操作,要有一个清屏函数,所以要有3个函数。
(1) fb初始化
(2) 显示函数
(3) 清屏函数
只有函数还不全,还需要一些属性,如定义一个名字“fb”,X坐标,Y坐标,多少位表示一个像素等属性。
disp_manager.h中结构体设计如下
typedef struct DispOpr {char *name;int iXres;int iYres;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;fb.c初始化结构体,并写出对应的函数。
static T_DispOpr g_tFBOpr = {.name = "fb",.DeviceInit = FBDeviceInit,.ShowPixel = FBShowPixel,.CleanScreen = FBCleanScreen,};
结构体用到这些函数 ,所以事先声明一下,都是static所以只能在本文件中使用,外面想用只能通过上一层。
static int FBDeviceInit(void);static int FBShowPixel(int iX, int iY, unsigned int dwColor);static int FBCleanScreen(unsigned int dwBackColor);
在哪注册?
int FBInit(void){return RegisterDispOpr(&g_tFBOpr);}
这里就不能写成static了。
注册就是把结构体加入链表中,链表比数组更灵活,大小随意。
一开始链表头是空的,所以让指针指向这个结构体。在注册就让next指向新结构体。
实现三个函数:
注意这里是应用程序所以是一些open,read等函数。
如:g_fd = open(FB_DEVICE_NAME, O_RDWR);
这里不应该把设备名字定死,所以写一个config文件
#ifndef _CONFIG_H#define _CONFIG_H#include <stdio.h>#define FB_DEVICE_NAME "/dev/fb0"#define COLOR_BACKGROUND 0xE7DBB5 /* 泛黄的纸 */#define COLOR_FOREGROUND 0x514438 /* 褐色字体 */#define DBG_PRINTF(...) //#define DBG_PRINTF printf#endif /* _CONFIG_H */
DBG_PRINTF:这个宏可以控制打印开关。
显示做好了,但是我们显示内容在哪呢?需要设置显示字体,得到显示的点阵。如显示ASCII还是ABK,还是freetype。同理写出这部分代码。
代码:
fb.c:重点是结构
#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; //FB屏幕大小static unsigned int g_dwLineWidth; //一行宽度:一行的像素*像素位数/8字节 static unsigned int g_dwPixelWidth; //每个像素占据多少字节:BPP/8=2字节(一个像素占据2字节)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;}//RRGGBB 16: 24转成565static 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);}disp_manager.c:重点是链表操作
#include <config.h>#include <disp_manager.h>#include <string.h>static PT_DispOpr g_ptDispOprHead;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;}void ShowDispOpr(void){int i = 0;PT_DispOpr ptTmp = g_ptDispOprHead;while (ptTmp){printf("%02d %s\n", i++, ptTmp->name);ptTmp = ptTmp->ptNext;}}PT_DispOpr GetDispOpr(char *pcName){PT_DispOpr ptTmp = g_ptDispOprHead;while (ptTmp){if (strcmp(ptTmp->name, pcName) == 0){return ptTmp;}ptTmp = ptTmp->ptNext;}return NULL;}int DisplayInit(void){int iError;iError = FBInit();return iError;}
2、字体部分编写
3、编码部分编写
三、分层编写-上层实现
1、draw.c
2、main.c
解析命令-打开文本-显示文本-换页-返回上一页等
#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <config.h>#include <draw.h>#include <encoding_manager.h>#include <fonts_manager.h>#include <disp_manager.h>#include <string.h>/* ./show_file [-s Size] [-f freetype_font_file] [-h HZK] <text_file> */int main(int argc, char **argv){int iError;unsigned int dwFontSize = 16;char acHzkFile[128];char acFreetypeFile[128];char acTextFile[128];char acDisplay[128];char cOpr;int bList = 0;acHzkFile[0] = '\0';acFreetypeFile[0] = '\0';acTextFile[0] = '\0';strcpy(acDisplay, "fb");while ((iError = getopt(argc, argv, "ls:f:h:d:")) != -1){switch(iError){case 'l':{ bList = 1; break;}case 's':{ dwFontSize = strtoul(optarg, NULL, 0); break;}case 'f':{ strncpy(acFreetypeFile, optarg, 128); acFreetypeFile[127] = '\0'; break;}case 'h':{strncpy(acHzkFile, optarg, 128);acHzkFile[127] = '\0';break;}case 'd':{strncpy(acDisplay, optarg, 128);acDisplay[127] = '\0';break;}default:{printf("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);printf("Usage: %s -l\n", argv[0]);return -1;break;}}}if (!bList && (optind >= argc)){printf("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);printf("Usage: %s -l\n", argv[0]);return -1;}iError = DisplayInit();if (iError){printf("DisplayInit error!\n");return -1;}iError = FontsInit();if (iError){printf("FontsInit error!\n");return -1;}iError = EncodingInit();if (iError){printf("EncodingInit error!\n");return -1;}if (bList){printf("supported display:\n");ShowDispOpr();printf("supported font:\n");ShowFontOpr();printf("supported encoding:\n");ShowEncodingOpr();return 0;}strncpy(acTextFile, argv[optind], 128);acTextFile[127] = '\0';iError = OpenTextFile(acTextFile);if (iError){printf("OpenTextFile error!\n");return -1;}iError = SetTextDetail(acHzkFile, acFreetypeFile, dwFontSize);if (iError){printf("SetTextDetail error!\n");return -1;}DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);iError = SelectAndInitDisplay(acDisplay);if (iError){printf("SelectAndInitDisplay error!\n");return -1;}DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);iError = ShowNextPage();DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);if (iError){printf("Error to show first page\n");return -1;}while (1){printf("Enter 'n' to show next page, 'u' to show previous page, 'q' to exit: ");do {cOpr = getchar();} while ((cOpr != 'n') && (cOpr != 'u') && (cOpr != 'q'));if (cOpr == 'n'){ShowNextPage();}else if (cOpr == 'u'){ShowPrePage();}else {return 0;}}return 0;}(1)解析命令参数
getopt(argc, argv, "ls:f:h:d:")
:需要带参数
-l 不需要带参数strncpy(acTextFile, argv[optind], 128);得到文件名
(2)初始化显示、字体、编码--》注册相关结构体
iError = DisplayInit();iError = FontsInit();iError = EncodingInit();(3)打开文件
OpenTextFile(acTextFile)
(4)打开字体文件
SetTextDetail(acHzkFile, acFreetypeFile, dwFontSize);
(5)根据名字选择初始化一个显示器
SelectAndInitDisplay(acDisplay);
(6)显示第一页或者下一页
ShowNextPage();
(7)等待命令参数,显示下一页,上一页等
- linux应用项目(一)数码相框(3)数码相框之电子书
- linux应用项目(一)数码相框(1)数码相框之系统框架
- linux应用项目(一)数码相框(2)数码相框之freetype实现矢量字体的显示
- linux应用项目(一)数码相框(2)数码相框之字符编码与字符的点阵显示
- 数码相框项目
- 数码相框项目之LCD模块
- 数码相框项目之触摸屏模块
- 数码相框项目模块【一】 跑马灯
- 韦东山第三期视频数码相框中的电子书项目的ShowOnePage函数解析
- 数码相框
- 数码相框笔记
- 数码相框项目模块【二】 UART
- 数码相框项目模块【三】 KEY
- 数码相框项目模块【四】 TIMER
- 1.数码相框之框架
- 数码相框——矢量字体原理(3)
- 【Linux开发】linux设备驱动归纳总结(十二):简单的数码相框
- 数码相框——矢量字体原理(6)
- STM32上使用UCOSII--软件定时器和任务延时
- appium环境搭建
- SOA架构
- Codeforces 330D Biridian Forest【思维+Bfs】
- 并行-Guarded Suspension模式
- linux应用项目(一)数码相框(3)数码相框之电子书
- 好题-Round #426 (Div. 2)C-二分&&思维||质因数分解-The Meaningless Game
- 62. Unique Paths 自己写的一次ac
- PHP——底层运行机制与原理
- Retrofit2 简单的使用
- mybatis整合springmvc遇到的问题(待解决)
- Fork/Join框架介绍
- matlab 写文件去掉科学计数法
- 利用redis的表达式实现速率请求控制器