注:本人已购买韦东山第三期项目视频,内容来源《数码相框项目视频》,只用于学习记录,如有侵权,请联系删除。
在数码相框(六、在LCD上显示任意编码的文本文件)中,我们以面向对象的思想实现了在LCD上显示电子书,应用程序框架如下图所示:
对于每一个模块,我们都会抽象出一个结构体,然后分配、设置、注册这个结构体。例如,在显示模块中,我们抽象出了T_DispOpr这个结构体,并且在fb.c中分配、设置、注册了一个T_DispOpr结构体,实现了LCD的初始化、像素显示等功能。这一节我们添加 crt.c 实现在PC上显示电子书。
1. 补充知识
(1) 在虚拟机中按下:
- 组合键:ctrl+alt+f1…f6 : 进入某一个文本终端
- 组合键:alt+f1…f6:进行选择进入哪一个文本终端
- 组合键:alt+f7:进入图形界面
(2) 在ubuntu虚拟机中,按下ctrl+alt+f3 进入tty3文本终端,如下图所示:
按下ctrl+alt+f4 进入tty4文本终端,如下图所示:
然后在Ubuntu的串口终端输入命令:echo hello > /dev/tty3
,在 tty3 文本终端可以看到打印出 hello 字符串,如下图所示:
在 tty3 文本终端输入命令:echo hello > /dev/tty4
,在 tty4 文本终端可以也看到打印出 hello 字符串,如下图所示:
从上面的实验我们可以猜测,在我们的硬件上只有一套LCD,但是软件上有众多的虚拟终端。当我们使用某一个tty终端时,就会在下面产生一个临时缓冲区buffer(如下图所示),内核会把对应buffer中的数据放入LCD显示出来。
如上图所示:
- 虚拟终端合用一个LCD硬件,通过临时缓冲区buffer区分是哪一个终端在使用硬件,一般来说,tty0表示当前的终端;
- 对于tty这一套系统来说,可以通过 /dev/tty? 来访问,它有两种模式:①文本模式,②图形模式;
2. 在tty图形模式中如何显示电子书?
2.1 环境搭建
(1) 下载 svgalib:
- 下载地址:https://launchpad.net/ubuntu/+source/svgalib/1:1.4.3-30
- 下载文件:svgalib_1.4.3.orig.tar.gz (源码)
svgalib_1.4.3-30.debian.tar.gz (针对ubuntu所做的补丁)
svgalib_1.4.3-30.dsc (描述文件,不重要)
(2) 解压:
tar xzf svgalib_1.4.3.orig.tar.gz
tar xzf svgalib_1.4.3-30.debian.tar.gz
(3) 打补丁
cd svgalib-1.4.3.orig/
for file in ../debian/patches/*.patch; do patch -p1 < $file;done
(4) 编译安装
sudo make install
编译会出现如下错误:
根据错误信息,缺少 libx86.h 这个头文件。需要安装 libx86 库:
sudo apt-get install libx86-dev
重新编译安装,成功。
2.2 测试编写程序
2.2.1 测试程序的代码如下:
#include <stdlib.h>
#include <vga.h>
#include <vgagl.h>
/* gcc -o svgatest svgatest.c -lvga -lvgagl */
int main(void)
{
int x, y;
vga_init();
vga_setmode(G320x200x256);
/* 设置调色板 */
gl_setpalettecolor(4, 0xE7>>2, 0xDB>>2, 0xB5>>2); /* 0xE7DBB5 */ /* 泛黄的纸 */
vga_setcolor(4);
for (x = 0; x < 320; x++)
for (y = 0; y < 200; y++)
vga_drawpixel(x, y);
sleep(5);
vga_setmode(TEXT);
return EXIT_SUCCESS;
}
编译运行处程序,本应该会在ubuntu上显色出泛黄色的背景色,但是可能是我虚拟机(我使用的虚拟机是Ubuntu-20.04)的原因,运行程序后,没有显色出泛黄色的背景色,而且虚拟机再也不能返回图形界面了,尝试了很多方法也无济于事,运行后显示结果下图所示,有哪位大神知道什么原因吗?求指教。
2.1.2 调色板
上面程序涉及到调色板的知识,在软件上使用8位数据表示一个像素(8bpp)时,但是硬件至少使用16位或者24位表示一个像素(16/24bpp),那么怎么转换,此时就需要调色板了,如下图所示:更多关于调色板的知识课查看:https://www.cnblogs.com/ganrui/p/3694744.html
其中,void gl_setpalettecolor(int c, int r, int g, int b);
意思是把r、g、b组成的颜色,放到编号为c的调色板格子里。
2.1.2 编写 crt.c 代码
#include <vga.h>
#include <vgagl.h>
#include <stdlib.h>
#include <disp_manager.h>
#include <config.h>
static int CRTDeviceInit(void);
static int CRTDeviceExit(void);
static int CRTShowPixel(int iPenX, int iPenY, unsigned int dwColor);
static int CRTCleanScreen(unsigned int dwBackColor);
static T_DispOpr g_tCRTDispOpr = {
.name = "crt",
.DeviceInit = CRTDeviceInit,
.DeviceExit = CRTDeviceExit,
.ShowPixel = CRTShowPixel,
.CleanScreen = CRTCleanScreen,
};
static int CRTDeviceInit(void)
{
vga_init();
vga_setmode(G320x200x256);
g_tCRTDispOpr.iXres = 320;
g_tCRTDispOpr.iYres = 200;
g_tCRTDispOpr.iBpp = 1;
return 0;
}
static int CRTDeviceExit(void)
{
vga_setmode(TEXT);
return 0;
}
static int CRTShowPixel(int iPenX, int iPenY, unsigned int dwColor)
{
int iRed, iGreen, iBlue;
iRed = (dwColor >> 16) & 0xff;
iGreen = (dwColor >> 8) & 0xff;
iBlue = (dwColor >> 0) & 0xff;
/* 设置调色板 */ /* 0xE7DBB5 泛黄的纸 */
gl_setpalettecolor(5, iRed >> 2, iGreen >> 2, iBlue >> 2);
/* 选择第五颜色 */
vga_setcolor(5);
/* 显示 */
vga_drawpixel(iPenX, iPenY);
return 0;
}
static int CRTCleanScreen(unsigned int dwBackColor)
{
int iRed, iGreen, iBlue;
int iPenX;
int iPenY;
iRed = (dwBackColor >> 16) & 0xff;
iGreen = (dwBackColor >> 8) & 0xff;
iBlue = (dwBackColor >> 0) & 0xff;
gl_setpalettecolor(4, iRed >> 2, iGreen >> 2, iBlue >> 2);
vga_setcolor(4);
for (iPenX = 0; iPenX < 320; iPenX++)
for (iPenY = 0; iPenY < 200; iPenY++)
vga_drawpixel(iPenX, iPenY);
return 0;
}
int CRTInit(void)
{
return RegisterDispOpr(&g_tCRTDispOpr);
}
由于前面所说的虚拟机问题,本次实验并没有成功,这是整个工程的代码:数码相框之PC(Ubuntu)显示电子书