-
包含:disp_manager.c/h、framebuffer.c/h模块
- disp_manager.c/h:显示管理器
- framebuffer.c/h:底层显示模块
-
disp_manager.c/h:数据显示部分在显示管理器的管理之下,支持多种方式进行数据显示,显示管理器可以向主线程提供数据显示的通用API**,也可以向底层显示设备提供通用的结构体,以方便底层显示设备可以注册进显示管理器供主线程使用,显示管理器向主线程提供的通用**API如下:
//provide with model of disp_manager.c to display device int putPixel(int x, int y, unsigned int dwColor); //绘制单个像素点 void dispDevRegister(PDispDev_S pDispDev); //注册某个底层显示设备到显示管理器 //provide with model of disp_manager.c to disp_test.c/user void dispSystemRegister(void); //注册所有底层显示设备 int selectDefaultDispDev(char* pName); //选择一个显示设备
int defaultDispDevInit(void); //初始化已经选择的显示设备 void dispDefaultDev(int x, int y, unsigned char c);//在buffer中显示数据 int flushDispRegion(PDispRegion_S pDispRegion, PDispBuffer_S pDispBuffer); //把buffer中的数据刷到显示设备的内存中 PDispBuffer_S getDispBuffer(void);//获取buffer
显示管理器用`DispDev`结构体描述底层显示设备,用`DispBuffer`结构体描述显示`buffer`,用结构体`DispRegion`描述`buffer`刷新到硬件显示内存的哪个区域,只有当显示`buffer`刷新到硬件显存之后,数据才会真正的显示;底层显示设备使用显示管理器提供的`int putPixel(int x, int y, unsigned int dwColor)`函数构造自己的数据显示函数,从而在提供给显示管理器,底层显示设备使用`dispDevRegister`函数把自己的`DispDev`结构体注册进显示管理器,显示管理器通过链表的形式把所有显示设备连接起来,需要使用的时候就在链表中查询
```C++
typedef struct DispBuffer
{
int xRes;
int yRes;
int bpp;
char* pBuffer;
}DispBuffer_S, *PDispBuffer_S;
typedef struct DispDev
{
char* pName;
int (*dispDevInit)(void);
int (*dispDevExit)(void);
int (*getDispBuffer)(PDispBuffer_S pDispBuffer);
void (*dispDev)(int x, int y, unsigned char c);
int (*flushDispRegion)(PDispRegion_S pDispRegion, PDispBuffer_S pDispBuffer);
struct DispDev* pNext;
}DispDev_S, *PDispDev_S;
-
包含:input_manager.c/h、netinput.c/h、touchscreen.c/h模块
- input_manager.c/h:输入管理器
- netinput.c/h:网络输入模块
- touchscreen.c/h:LCD输入模块
-
数据输入部分在输入管理器的管理之下,支持多种方式输入数据,输入管理器主要向主线程提供通用的API函数,屏蔽掉底层硬件复杂的操作逻辑,同时对底层硬件进行抽象管理,用链表连接每个硬件设备,对于需要使用的硬件设备,只需要注册进输入管理器即可
-
输入管理器提供给主线程的通用API:
//provide with model of input_manager.c to input device void inputDevRegister(PInputDevice_S ptInputDev); //注册底层硬件输入设备到输入管理器 //provide with model of input_manager.c to input_test.c/user
void inputSystemRegister(void); //注册所有底层输入设备 int inputDeviceInit(void); //初始化所有输入设备 int userGetInputEventData(PInputEvent_S pInputEvent); //获取输入数据
输入管理器抽象出`InputDevice`结构体用来描述每个硬件输入设备
```C++
typedef struct InputDevice
{
char* name; //设备名
int (*inputDevInit)(void); //设备初始化函数
int (*inputDevExit)(void); //设备卸载函数
int (*getInputEvent)(PInputEvent_S pInputEvent); //获取设备的输入数据
struct InputDevice* pNext; //指向注册进输入管理器的下一个设备InputDevice结构体
}InputDevice_S, * PInputDevice_S;
其中InputEvent
结构体用来描述硬件设备输入的一次完整数据
typedef struct InputEvent
{
int type; //数据类型,触摸输入 or 网络输入
int x; //触摸屏X坐标
int y; //触摸屏Y坐标
int pressure; //压力
char str[1024]; //网络输入的字符串
struct timeval time; //系统后的时间
}InputEvent_S, * PInputEvent_S;
底层硬件输入设备通过输入管理器提供的函数inputDevRegister
把自己注册进输入管理器
-
touchscreen.c/h:通过tslib库实现数据的读取,然后放进InputEvent,而netinput.c/h通过UDP协议获取数据,然后放进InputEvent结构体
-
数据读取的过程:
- inputDeviceInit函数会为每个底层输入设备创建一个数据读取线程,当有数据输入的时候,线程会把数据读取回来,然后放入环形buffer,然后通过pthread_cond_signal唤醒userGetInputEventData函数从环形buf读取数据
- 当环形buf没有数据的时候,userGetInputEventData会阻塞在pthread_cond_wait函数处
-
交叉编译zlib-1.2.11:
- 下载
wget http://www.zlib.net/fossils/zlib-1.2.11.tar.gz
- 解压
tar -zxvf zlib-1.2.11.tar.gz
- 指定工具链
export CC=arm-linux-gnueabihf-gcc
- 编译
cd /zlib-1.2.11
./configure --prefix=./tmp
make
make install
- 把交叉编译生成的头文件放入工具链
cd zlib-1.2.11/tmp
cp include/* /home/yhd_wsl2/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include
cp -d lib/*so* /home/yhd_wsl2/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/
-
交叉编译
libpng1.6.37
- 解压
tar xJf libpng-1.6.37.tar.xz
- 编译
./configure --host=arm-linux-gnueabihf --prefix=$PWD/tmp
make
make install
- 把交叉编译生成的头文件放入工具链
libpng-1.6.37/tmp
cp include/* -rf /home/yhd_wsl2/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include
cp lib/* -rfd /home/yhd_wsl2/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/
-
交叉编译
bzip2-1.0.6
- 下载
wget https://sourceforge.net/projects/bzip2/files/bzip2-1.0.6.tar.gz
- 解压
tar -zxvf bzip2-1.0.6.tar.gz
- 编译
cd bzip2-1.0.6
vim Makefile
vim Makefile-libbz2_so
make && make install
- 把交叉编译生成的头文件放入工具链
cd bzip2-1.0.6/tmp
cp include/* -rf /home/yhd_wsl2/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include
cp lib/* -rfd /home/yhd_wsl2/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/
cd bzip2-1.0.6
ln -s libbz2.so.1.0.6 libbz2.so
cp libbz2.so* -rfd /home/yhd_wsl2/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/
-
交叉编译
freetype-2.10.2
- 解压
tar xJf freetype-2.10.2
- 编译
./configure --host=arm-linux-gnueabihf --prefix=$PWD/tmp
make
make install
- 把交叉编译生成的头文件放入工具链
cd freetype-2.10.2/tmp
cp include/* -rf /home/yhd_wsl2/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include
cp lib/* -rfd /home/yhd_wsl2/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/
-
包含:font_manager.c/h、freetype.c/h等模块
- font_manager.c/h:字体管理器
- freetype.c/h:底层字体处理引擎
-
字体管理器抽象出
FontLib
结构体用来描述不同的字体管理工具,通过该结构体可以返回显示字符的点阵位图
typedef struct FontLib
{
char * pName;
int (*fontInit)(char * pFontFileName);
int (*setFontSize)(int fontSize);
int (*getFontBitMap)(unsigned int fontCode, PFontBitMap_S pFontBitMap);
int (*getStrBoxRegionCar)(char * pStr, PDispRegionCartesian_S pDispRegionCartesian);
struct FontLib *pNext;
}FontLib_S, * PFontLib_S;
其中FontBitMap
结构体用来描述一个字符的位图
typedef struct FontBitMap
{
DispRegion_S region;
int curOriginX;
int curOriginY;
int nextOriginX;
int nextOriginY;
unsigned char *pBuffer;
}FontBitMap_S, * PFontBitMap_S;
字体管理器也起着呈上启下的作用,向用户提供简单字体处理函数:
//provide with model of font_manager.c to font lib
void fontlibRegister(PFontLib_S pFontLib); //注册底层单个字库处理工具,freetype,点阵字库等
//provide with model of font_manager.c to font_test.c/user
void fontsLibSystemRegister(void); //把支持的所有字库处理工具注册到管理器
int selectAndInitFontLib(char * pFontLibName, char * pFontFileName);//选择并且初始化字库,打开字体文件
int setFontSize(int fontSize); //设置字体大小
int getFontBitMap(unsigned int fontCode, PFontBitMap_S pFontBitMap); //获得字符的位图
int getStrBoxRegionCar(char *pStr, PDispRegionCartesian_S pDispRegionCartesian); //获取字符串的外框
向底层字库管理工具提供注册函数
void fontlibRegister(PFontLib_S pFontLib)
同时在显示管理器中实现位图显示函数,把字符的位图信息写到显示buffer中
void drawFontBitMap(PFontBitMap_S pFontBitMap, unsigned int dwColor);
最后通过显示管理器提供的函数flushDispRegion
把数据刷到显存中
int flushDispRegion(PDispRegion_S pDispRegion, PDispBuffer_S pDispBuffer)
- 包含:ui.h、ui.button.c
- 通过抽象一个
UiButton
结构体来描述一个LCD显示器上的虚拟按钮
typedef struct UiButton
{
char * pName; //按钮名字
int status; //按钮状态
int fontSize; //按钮名字的字体
DispRegion_S region; //按钮的显示区域
PDrawButtonFunc pDrawButton; //绘制按钮的函数
PPressedButtonFunc pPressedButton; //按钮按下调用的函数
}UiButton_S, *PUiButton_S;
用户通过调用initButton
函数初始化一个按钮,其中pDrawButton
和pPressedButton
可以由用户提供,也可以使用默认的函数
-
包含page_manager.c/h、mainpage.c/h模块
- page_manager.c/h:页面管理器
- mainpage.c/h:底层页面模块
-
页面管理器通过抽象结构体PageAction来描述一个底层的页面模块
typedef struct PageAction { char * pName; //底层页面的名字 void (*run)(void * pParams); //底层页面对应的响应函数 struct PageAction * pNext; //所有页面通过链表进行存储 }PageAction_S, * PPageAction_S;
页面管理器向底层页面模块,比如mainpage.c/h,提供注册函数pageRegister,底层页面便可以把实现的PageAction结构体注册到页面管理器中,页面管理器可以向用户提供简单页面处理接口:
//provide with model of page_manager.c to page_action void pageRegister(PPageAction_S pPageAction); //注册某一个底层页面 //provide with model of page_manager.c to user/page_test.c PPageAction_S selectPage(char * pName); //选择需要使用的底层页面 void pageSystemRegister(void); //注册所有底层页面
- 初始化显示系统、输入系统、字体系统、页面系统,调用主页面,在主页面中读取配置文件,根据配置文件生成按钮界面,然后等待事件缓冲区有数据便可以读取事件,根据事件找到对应的输入设备(按钮、网络输入),然后执行相应的响应函数
-
包含degug_manager.c/h、netprint.c、stdout.c模块
- degug_manager.c/h:调试管理器
- netprint.c:底层网络调试模块
- stdout.c:标准输出调试模块
-
调试管理器通过抽象DebugOpr结构体来描述底层调试模块
typedef struct DebugOpr { char *name; //调试模块名字 int isCanUse; //模块使能 int (*DebugInit)(void); /* 调试模块的初始化函数 */ int (*DebugExit)(void); /* 退出函数 */ int (*DebugPrint)(char *strData); /* 输出函数 */ struct DebugOpr *ptNext; //调试管理器通过链表管理底层调试模块 }T_DebugOpr, *PT_DebugOpr;
-
页面管理器向底层调试模块提供RegisterDebugOpr函数,底层模块可以通过该函数把具体填充的DebugOpr结构体注册到调试管理器中
-
页面管理器向用户提供以下API
void ShowDebugOpr(void);//打印系统支持调试模块 PT_DebugOpr GetDebugOpr(char *pcName);//获得调试模块的结构体 int SetDbgLevel(char *strBuf);//设置调试信息打印等级 int SetDbgChanel(char *strBuf);//选择打印模块 int DebugInit(void);//注册调试管理器中的调试模块 int DebugPrint(const char *pcFormat, ...);//通过调试模块输出调试信息 int InitDebugChanel(void); //调用底层调试模块的初始化函数
-
调试信息只有超过g_iDbgLevelLimit这个级别,才能被输出
-
-
底层调试模块的具体实现原理:
- stdout.c标准输出调试模块通过printf函数实现
- netprint.c底层网络调试模块基于UDP协议实现,该模块会初始化为一个UDP服务器,并且创建发送线程、接受线程、环形缓冲区。接受线程可以接受客户端的命令,实现设置打印级别,使能/失能打印模块。当上层进行数据打印的时候,netprint.c中的打印函数会把数据存入环形缓冲区,并且唤醒发送线程,发送线程从环形缓冲区取出数据然后便可以发送给客户端进行显示