当前位置:   article > 正文

linux应用项目(一)数码相框(3)数码相框之电子书_数码相框 开源项目

数码相框 开源项目

一、整体思路

这一节我们重点学习框架,就是编程的思想。架构很重要。采用分层的思想,面向对象的编程思想。


1、怎样在LCD上显示一个文件


2、如何组织代码

分层的结构

main--draw--XXX_manager--fb.c等



二、分层编写-底层实现

1、显示部分代码编写

  1. show_file\display\fb.c
  2. show_file\display\disp_manager.c
  3. show_file\include\config.h
  4. show_file\include\disp_manager.h
  5. show_file\draw\draw.c

先写fb.c 一面向对象编程思想

设置构造一个结构体

结构体需要有哪些成员呢:

显示部分,一定有一个显示函数,FB要显示就要初始化,所以有一个fb初始化函数,换页的时候我们要进行清屏操作,要有一个清屏函数,所以要有3个函数。

(1)    fb初始化

(2)    显示函数

(3)    清屏函数

只有函数还不全,还需要一些属性,如定义一个名字“fb”,X坐标,Y坐标,多少位表示一个像素等属性。

disp_manager.h中结构体设计如下

  1. typedef struct DispOpr {
  2. char *name;
  3. int iXres;
  4. int iYres;
  5. int iBpp;
  6. int (*DeviceInit)(void);
  7. int (*ShowPixel)(int iPenX, int iPenY, unsigned int dwColor);
  8. int (*CleanScreen)(unsigned int dwBackColor);
  9. struct DispOpr *ptNext;
  10. }T_DispOpr, *PT_DispOpr;
fb.c初始化结构体,并写出对应的函数。
  1. static T_DispOpr g_tFBOpr = {
  2. .name = "fb",
  3. .DeviceInit = FBDeviceInit,
  4. .ShowPixel = FBShowPixel,
  5. .CleanScreen = FBCleanScreen,
  6. };

结构体用到这些函数 ,所以事先声明一下,都是static所以只能在本文件中使用,外面想用只能通过上一层。

  1. static int FBDeviceInit(void);
  2. static int FBShowPixel(int iX, int iY, unsigned int dwColor);
  3. static int FBCleanScreen(unsigned int dwBackColor);

在哪注册?

  1. int FBInit(void)
  2. {
  3. return RegisterDispOpr(&g_tFBOpr);
  4. }

这里就不能写成static了。

注册就是把结构体加入链表中,链表比数组更灵活,大小随意。

一开始链表头是空的,所以让指针指向这个结构体。在注册就让next指向新结构体。

实现三个函数:

注意这里是应用程序所以是一些open,read等函数。

如:g_fd = open(FB_DEVICE_NAME, O_RDWR);

这里不应该把设备名字定死,所以写一个config文件

  1. #ifndef _CONFIG_H
  2. #define _CONFIG_H
  3. #include <stdio.h>
  4. #define FB_DEVICE_NAME "/dev/fb0"
  5. #define COLOR_BACKGROUND 0xE7DBB5 /* 泛黄的纸 */
  6. #define COLOR_FOREGROUND 0x514438 /* 褐色字体 */
  7. #define DBG_PRINTF(...)
  8. //#define DBG_PRINTF printf
  9. #endif /* _CONFIG_H */

DBG_PRINTF:这个宏可以控制打印开关。

显示做好了,但是我们显示内容在哪呢?需要设置显示字体,得到显示的点阵。如显示ASCII还是ABK,还是freetype。同理写出这部分代码。

代码:

fb.c:重点是结构

  1. #include <config.h>
  2. #include <disp_manager.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <fcntl.h>
  6. #include <sys/ioctl.h>
  7. #include <sys/mman.h>
  8. #include <linux/fb.h>
  9. #include <string.h>
  10. static int FBDeviceInit(void);
  11. static int FBShowPixel(int iX, int iY, unsigned int dwColor);
  12. static int FBCleanScreen(unsigned int dwBackColor);
  13. static int g_fd;
  14. static struct fb_var_screeninfo g_tFBVar; //可变参数
  15. static struct fb_fix_screeninfo g_tFBFix; //固定参数
  16. static unsigned char *g_pucFBMem; //内存映射
  17. static unsigned int g_dwScreenSize; //FB屏幕大小
  18. static unsigned int g_dwLineWidth; //一行宽度:一行的像素*像素位数/8字节
  19. static unsigned int g_dwPixelWidth; //每个像素占据多少字节:BPP/8=2字节(一个像素占据2字节)
  20. static T_DispOpr g_tFBOpr = {
  21. .name = "fb",
  22. .DeviceInit = FBDeviceInit,
  23. .ShowPixel = FBShowPixel,
  24. .CleanScreen = FBCleanScreen,
  25. };
  26. static int FBDeviceInit(void)
  27. {
  28. int ret;
  29. g_fd = open(FB_DEVICE_NAME, O_RDWR);
  30. if (0 > g_fd)
  31. {
  32. DBG_PRINTF("can't open %s\n", FB_DEVICE_NAME);
  33. }
  34. ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar);
  35. if (ret < 0)
  36. {
  37. DBG_PRINTF("can't get fb's var\n");
  38. return -1;
  39. }
  40. ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);
  41. if (ret < 0)
  42. {
  43. DBG_PRINTF("can't get fb's fix\n");
  44. return -1;
  45. }
  46. g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8;
  47. g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);
  48. if (0 > g_pucFBMem)
  49. {
  50. DBG_PRINTF("can't mmap\n");
  51. return -1;
  52. }
  53. g_tFBOpr.iXres = g_tFBVar.xres;
  54. g_tFBOpr.iYres = g_tFBVar.yres;
  55. g_tFBOpr.iBpp = g_tFBVar.bits_per_pixel; //设置坐标和多少位表示一个像素
  56. g_dwLineWidth = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;
  57. g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;
  58. return 0;
  59. }
  60. //RRGGBB 16: 24转成565
  61. static int FBShowPixel(int iX, int iY, unsigned int dwColor)
  62. {
  63. unsigned char *pucFB;
  64. unsigned short *pwFB16bpp;
  65. unsigned int *pdwFB32bpp;
  66. unsigned short wColor16bpp; /* 565 */
  67. int iRed;
  68. int iGreen;
  69. int iBlue;
  70. if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres))
  71. {
  72. DBG_PRINTF("out of region\n");
  73. return -1;
  74. }
  75. pucFB = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;
  76. pwFB16bpp = (unsigned short *)pucFB;
  77. pdwFB32bpp = (unsigned int *)pucFB;
  78. switch (g_tFBVar.bits_per_pixel)
  79. {
  80. case 8:
  81. {
  82. *pucFB = (unsigned char)dwColor;
  83. break;
  84. }
  85. case 16:
  86. {
  87. iRed = (dwColor >> (16+3)) & 0x1f;
  88. iGreen = (dwColor >> (8+2)) & 0x3f;
  89. iBlue = (dwColor >> 3) & 0x1f;
  90. wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
  91. *pwFB16bpp = wColor16bpp;
  92. break;
  93. }
  94. case 32:
  95. {
  96. *pdwFB32bpp = dwColor;
  97. break;
  98. }
  99. default :
  100. {
  101. DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);
  102. return -1;
  103. }
  104. }
  105. return 0;
  106. }
  107. static int FBCleanScreen(unsigned int dwBackColor)
  108. {
  109. unsigned char *pucFB;
  110. unsigned short *pwFB16bpp;
  111. unsigned int *pdwFB32bpp;
  112. unsigned short wColor16bpp; /* 565 */
  113. int iRed;
  114. int iGreen;
  115. int iBlue;
  116. int i = 0;
  117. pucFB = g_pucFBMem;
  118. pwFB16bpp = (unsigned short *)pucFB;
  119. pdwFB32bpp = (unsigned int *)pucFB;
  120. switch (g_tFBVar.bits_per_pixel)
  121. {
  122. case 8:
  123. {
  124. memset(g_pucFBMem, dwBackColor, g_dwScreenSize);
  125. break;
  126. }
  127. case 16:
  128. {
  129. iRed = (dwBackColor >> (16+3)) & 0x1f;
  130. iGreen = (dwBackColor >> (8+2)) & 0x3f;
  131. iBlue = (dwBackColor >> 3) & 0x1f;
  132. wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
  133. while (i < g_dwScreenSize)
  134. {
  135. *pwFB16bpp = wColor16bpp;
  136. pwFB16bpp++;
  137. i += 2;
  138. }
  139. break;
  140. }
  141. case 32:
  142. {
  143. while (i < g_dwScreenSize)
  144. {
  145. *pdwFB32bpp = dwBackColor;
  146. pdwFB32bpp++;
  147. i += 4;
  148. }
  149. break;
  150. }
  151. default :
  152. {
  153. DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);
  154. return -1;
  155. }
  156. }
  157. return 0;
  158. }
  159. int FBInit(void)
  160. {
  161. return RegisterDispOpr(&g_tFBOpr);
  162. }
disp_manager.c:重点是链表操作

  1. #include <config.h>
  2. #include <disp_manager.h>
  3. #include <string.h>
  4. static PT_DispOpr g_ptDispOprHead;
  5. int RegisterDispOpr(PT_DispOpr ptDispOpr)
  6. {
  7. PT_DispOpr ptTmp;
  8. if (!g_ptDispOprHead)
  9. {
  10. g_ptDispOprHead = ptDispOpr;
  11. ptDispOpr->ptNext = NULL;
  12. }
  13. else
  14. {
  15. ptTmp = g_ptDispOprHead;
  16. while (ptTmp->ptNext)
  17. {
  18. ptTmp = ptTmp->ptNext;
  19. }
  20. ptTmp->ptNext = ptDispOpr;
  21. ptDispOpr->ptNext = NULL;
  22. }
  23. return 0;
  24. }
  25. void ShowDispOpr(void)
  26. {
  27. int i = 0;
  28. PT_DispOpr ptTmp = g_ptDispOprHead;
  29. while (ptTmp)
  30. {
  31. printf("%02d %s\n", i++, ptTmp->name);
  32. ptTmp = ptTmp->ptNext;
  33. }
  34. }
  35. PT_DispOpr GetDispOpr(char *pcName)
  36. {
  37. PT_DispOpr ptTmp = g_ptDispOprHead;
  38. while (ptTmp)
  39. {
  40. if (strcmp(ptTmp->name, pcName) == 0)
  41. {
  42. return ptTmp;
  43. }
  44. ptTmp = ptTmp->ptNext;
  45. }
  46. return NULL;
  47. }
  48. int DisplayInit(void)
  49. {
  50. int iError;
  51. iError = FBInit();
  52. return iError;
  53. }

2、字体部分编写

思路如上一样,分配、设置、注册结构体。

3、编码部分编写

思路如上一样,分配、设置、注册结构体。

三、分层编写-上层实现

1、draw.c

组织底层代码

2、main.c

解析命令-打开文本-显示文本-换页-返回上一页等

  1. #include <unistd.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <config.h>
  5. #include <draw.h>
  6. #include <encoding_manager.h>
  7. #include <fonts_manager.h>
  8. #include <disp_manager.h>
  9. #include <string.h>
  10. /* ./show_file [-s Size] [-f freetype_font_file] [-h HZK] <text_file> */
  11. int main(int argc, char **argv)
  12. {
  13. int iError;
  14. unsigned int dwFontSize = 16;
  15. char acHzkFile[128];
  16. char acFreetypeFile[128];
  17. char acTextFile[128];
  18. char acDisplay[128];
  19. char cOpr;
  20. int bList = 0;
  21. acHzkFile[0] = '\0';
  22. acFreetypeFile[0] = '\0';
  23. acTextFile[0] = '\0';
  24. strcpy(acDisplay, "fb");
  25. while ((iError = getopt(argc, argv, "ls:f:h:d:")) != -1)
  26. {
  27. switch(iError)
  28. {
  29. case 'l':
  30. {
  31. bList = 1;
  32. break;
  33. }
  34. case 's':
  35. {
  36. dwFontSize = strtoul(optarg, NULL, 0);
  37. break;
  38. }
  39. case 'f':
  40. {
  41. strncpy(acFreetypeFile, optarg, 128);
  42. acFreetypeFile[127] = '\0';
  43. break;
  44. }
  45. case 'h':
  46. {
  47. strncpy(acHzkFile, optarg, 128);
  48. acHzkFile[127] = '\0';
  49. break;
  50. }
  51. case 'd':
  52. {
  53. strncpy(acDisplay, optarg, 128);
  54. acDisplay[127] = '\0';
  55. break;
  56. }
  57. default:
  58. {
  59. printf("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);
  60. printf("Usage: %s -l\n", argv[0]);
  61. return -1;
  62. break;
  63. }
  64. }
  65. }
  66. if (!bList && (optind >= argc))
  67. {
  68. printf("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);
  69. printf("Usage: %s -l\n", argv[0]);
  70. return -1;
  71. }
  72. iError = DisplayInit();
  73. if (iError)
  74. {
  75. printf("DisplayInit error!\n");
  76. return -1;
  77. }
  78. iError = FontsInit();
  79. if (iError)
  80. {
  81. printf("FontsInit error!\n");
  82. return -1;
  83. }
  84. iError = EncodingInit();
  85. if (iError)
  86. {
  87. printf("EncodingInit error!\n");
  88. return -1;
  89. }
  90. if (bList)
  91. {
  92. printf("supported display:\n");
  93. ShowDispOpr();
  94. printf("supported font:\n");
  95. ShowFontOpr();
  96. printf("supported encoding:\n");
  97. ShowEncodingOpr();
  98. return 0;
  99. }
  100. strncpy(acTextFile, argv[optind], 128);
  101. acTextFile[127] = '\0';
  102. iError = OpenTextFile(acTextFile);
  103. if (iError)
  104. {
  105. printf("OpenTextFile error!\n");
  106. return -1;
  107. }
  108. iError = SetTextDetail(acHzkFile, acFreetypeFile, dwFontSize);
  109. if (iError)
  110. {
  111. printf("SetTextDetail error!\n");
  112. return -1;
  113. }
  114. DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
  115. iError = SelectAndInitDisplay(acDisplay);
  116. if (iError)
  117. {
  118. printf("SelectAndInitDisplay error!\n");
  119. return -1;
  120. }
  121. DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
  122. iError = ShowNextPage();
  123. DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
  124. if (iError)
  125. {
  126. printf("Error to show first page\n");
  127. return -1;
  128. }
  129. while (1)
  130. {
  131. printf("Enter 'n' to show next page, 'u' to show previous page, 'q' to exit: ");
  132. do {
  133. cOpr = getchar();
  134. } while ((cOpr != 'n') && (cOpr != 'u') && (cOpr != 'q'));
  135. if (cOpr == 'n')
  136. {
  137. ShowNextPage();
  138. }
  139. else if (cOpr == 'u')
  140. {
  141. ShowPrePage();
  142. }
  143. else
  144. {
  145. return 0;
  146. }
  147. }
  148. return 0;
  149. }
(1)解析命令参数

getopt(argc, argv, "ls:f:h:d:")

:需要带参数

-l 不需要带参数

strncpy(acTextFile, argv[optind], 128);得到文件名

(2)初始化显示、字体、编码--》注册相关结构体

  1. iError = DisplayInit();
  2. iError = FontsInit();
  3. iError = EncodingInit();
(3)打开文件

 OpenTextFile(acTextFile)
(4)打开字体文件

SetTextDetail(acHzkFile, acFreetypeFile, dwFontSize);

(5)根据名字选择初始化一个显示器

SelectAndInitDisplay(acDisplay);
(6)显示第一页或者下一页

ShowNextPage();

(7)等待命令参数,显示下一页,上一页等


声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号