数码相册——电子书的实现
硬件平台:韦东山嵌入式Linxu开发板(S3C2440.v3)软件平台:运行于VMware Workstation 12 Player下UbuntuLTS16.04_x64 系统参考资料:《嵌入式Linux应用开发手册》、《嵌入式Linux应用开发手册第2版》开发环境:Linux 3.4.2内核、arm-linux-gcc 4.3.2工具链源码仓库:https://gitee.com/d_1254436976/Embedded-Linux-Phase-3
目录
数码相册——电子书的实现
一、大致框架1、框架图2、代码间的有效管理
二、`config.h`文件分析三、挑display显示部分来进行分析1、`disp_manager.h`文件分析2、`disp_manager.c`文件分析3、`fb.c`文件分析3.1 分配结构体3.2 设置结构体3.3 注册结构体3.4 完整文件
四、程序的运行1、编译2、执行3、现象
一、大致框架
1、框架图
对于在LCD中显示一个文件,总体上进行下面几件事:
去文件中获得编码信息,对于每个文件,保存的时候,系统对自动或手动的根据编码规范,对文件的信息进行编码:如保存为ASCII、GBK、UTF-8、UTF16LE、UTF16BE;根据获得的编码信息得到字体数据(LCD上表示为点阵);把字体数据(点阵)显示在LCD上。
所以根据这个信息,可以总结出上述的框架。
2、代码间的有效管理
对于上述完成主要功能的4个部分:encoding编码部分、fonts获取字体点阵部分、display显示部分、draw协调部分,会仿照Linux内核的方式采用模块化进行管理,对于每个部分:
在代码上实现一个manager,向下支持各种文件的拓展,把所支持的文件放入链表中进行管理;向上提供各种接口,使其可以根据实际情况进行从链表中选择不同的拓展文件来进行功能的实现。每个部分都会定义一个结构体变量,拓展文件可以根据自己的情况:分配结构体、设置结构体、注册结构体。对于每个部分之间进行数据的沟通,可以通过main.c和draw.c的协调,通过获得各个部分的结构体变量,在draw.c文件中进行交互。
二、config.h文件分析
对于这个文件,从名字就知道,它是一个配置文件,定义了一些宏定义,供所有文件调用
源码 对于#define DBG_PRINTF(...) 与 #define DBG_PRINTF printf: 当我们调试的时候,可以//#define DBG_PRINTF(...) #define DBG_PRINTF printf,打印调试信息; 当我们程序发布时,可以#define DBG_PRINTF(...) //#define DBG_PRINTF printf,屏蔽调试信息的打印。
#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 printf
#endif
三、挑display显示部分来进行分析
1、disp_manager.h文件分析
在这个文件中,定义了一个结构体和相关函数,供拓展文件来分配结构体、设置结构体、注册结构体
#ifndef _DISP_MANAGER_H
#define _DISP_MANAGER_H
typedef struct DispOpr
{
char *name
;
int Xres
;
int Yres
;
int Bpp
;
int (*DeviceInit
)(void);
int (*ShowPixel
)(int PenX
, int PenY
, unsigned int Color
);
int (*CleanScreen
)(unsigned int BackColor
);
struct DispOpr
*ptNext
;
}T_DispOpr
, *PT_DispOpr
;
int RegisterDispOpr(PT_DispOpr ptDispOpr
);
void ShowDispOpr(void);
int DisplayInit(void);
int FBInit(void);
#endif
2、disp_manager.c文件分析
这个文件就是负责上述disp_manager.h文件的函数实现:
#include <config.h>
#include <disp_manager.h>
#include <string.h>
static PT_DispOpr s_ptDispOprHead
;
int RegisterDispOpr(PT_DispOpr ptDispOpr
)
{
PT_DispOpr ptTmp
;
if (!s_ptDispOprHead
)
{
s_ptDispOprHead
= ptDispOpr
;
ptDispOpr
->ptNext
= NULL;
}
else
{
ptTmp
= s_ptDispOprHead
;
while (ptTmp
->ptNext
)
{
ptTmp
= ptTmp
->ptNext
;
}
ptTmp
->ptNext
= ptDispOpr
;
ptDispOpr
->ptNext
= NULL;
}
return 0;
}
void ShowDispOpr(void)
{
int i
= 0;
PT_DispOpr ptTmp
= s_ptDispOprHead
;
while (ptTmp
)
{
printf("d %s\n", i
++, ptTmp
->name
);
ptTmp
= ptTmp
->ptNext
;
}
}
PT_DispOpr
GetDispOpr(char *pName
)
{
PT_DispOpr ptTmp
= s_ptDispOprHead
;
while (ptTmp
)
{
if (strcmp(ptTmp
->name
, pName
) == 0)
{
return ptTmp
;
}
ptTmp
= ptTmp
->ptNext
;
}
return NULL;
}
int DisplayInit(void)
{
int error
;
error
= FBInit();
return error
;
}
3、fb.c文件分析
3.1 分配结构体
static T_DispOpr s_tFBDispOpr
= {
.name
= "fb",
.DeviceInit
= FBDeviceInit
,
.ShowPixel
= FBShowPixel
,
.CleanScreen
= FBCleanScreen
,
};
3.2 设置结构体
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_tFBDispOpr
.Xres
= s_tVar
.xres
;
s_tFBDispOpr
.Yres
= s_tVar
.yres
;
s_tFBDispOpr
.Bpp
= s_tVar
.bits_per_pixel
;
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_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;
}
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:
red
= ((Color
>> 16) & 0xffff) >> 3;
green
= ((Color
>> 8 ) & 0xffff) >> 2;
blue
= ((Color
>> 0 ) & 0xffff) >> 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;
}
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:
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;
}
break;
case 32:
for (i
= 0; i
< s_ScreenSize
;) {
*pPen32
= BackColor
;
pPen32
++;
i
+= 4;
}
break;
default:
DBG_PRINTF("can not surport