6.7 GUI man-machine interface

6.7.1 Origin

In daily communication, many people feel that there is a big gap between the design of a single module interface and the design of the overall product architecture. Everyone generally feels that the interface design of a single module is relatively easy, but once the overall product architecture design is started, there is no way to start. The static and dynamic program organization structure explained in the previous chapters should be considered as a relatively introductory knowledge in architecture design, but have you already begun to feel a little confused? How to crack it?

In the course of many years of practice, we have found a good middle hand: the overall design of complex modules. The so-called complex module is not a deterministic concept. It varies from person to person. For example, the fixed value module may already be a complex module for a newbie, but for a veteran who has worked for many years, the GUI modules in this chapter are all considered Not much complicated.

Complex modules are generally divided into multiple layers internally, composed of multiple software modules. In order to let everyone experience this middle hand, I choose a moderately complex and interesting software module: GUI module.

◇◇◇

The LCD size of industrial products is generally small, with few functions and easy to operate. Therefore, most of the early days did not have a clear GUI module. The LCD interface program first draws each interface through a series of interface functions such as drawing dots, lines, and strings, and then switches through buttons To achieve.

This program structure mixes interface logic and functional logic. To complete an interface, not only the specific displayed information content, such as the fixed value name unit, but also interface issues such as cursor switching and scrolling need to be considered. Not only causes each LCD interface program to be very complicated, but also a large amount of redundancy in each interface program, such as telemetry scrolling program and fixed value scrolling program. What's more serious is that this type of LCD interface program is tightly bound to the size of the LCD, and the program contains a large number of hard-coded positions.

The functions of early protection devices were relatively simple, and this strategy was simple and reliable. However, as the protection functions continued to increase, the number of LCD interfaces was also increasing rapidly. What is even more painful is that in order to meet the needs of the market and users, the LCD interface has become larger and larger, and there are LCDs of different sizes to meet different user needs. These requirements made the original program strategy infeasible.

In a project I participated in, not only did the LCD become larger and the dot matrix became denser, but also there were multiple LCD sizes. The original LCD interface program had no reuse value and needed to be rewritten. With this opportunity, can the LCD interface module be reconstructed?

◇◇◇

How to build a reusable LCD interface program, the computer industry has long given a standard answer: GUI module. As shown in the figure below: The
Insert picture description here
figure on the left is an operation diagram of the LCD interface for viewing the component status. The component status is organized in a table, the first column is the name, and the second column is the component status. When building such programs based on GUI modules, the pseudo code is as follows:

void onCreate(void)
{
	获取表格控件控制句柄
	for (i = 0; i < 元件个数; i++)
	{
		通过元件接口函数获取第i个元件名称及状态信息;
		表格第一列填充元件名称;
		表格第二列填充元件状态;
	}
}

This pseudo-code not only does not contain any hard-coded information of the LCD position, but also does not need to deal with the interface details such as cursor movement and screen turning. The interface programs are not only simple, but also easy to reuse.

GUI interface programs are often bound to resources, such as dialog box resources of windows programs. This type of resource isolates the difference of various liquid crystal sizes. Different liquid crystal sizes correspond to different interface resources. The interface program programs the controls, and all location information is hidden in the resource configuration file.

Therefore, the GUI module has become our first choice.

◇◇◇

There are many GUI modules on the market, which one should I choose? After repeated weighing, our team finally chose the ucGUI module, but we didn't expect everything to just start. (Note: The ucGUI module described in this book is the version of ucGUI in 2006, so there will be discrepancies in many contents. It is recommended that you focus on the iterative experience)

With ucGUI, the first problem is slow response. At that time, we were still using 68332cpu. In the case of ensuring the priority of the protection task, the CPU resources were already a bit tight. At this time, running the ucGUI module, you can clearly see the refreshing process of the LCD screen, and you need to wait 1~2s after pressing the key. The LCD interface is responsive, and the user experience is poor.

The second is about the support of Chinese characters. The flash resources of the relay protection equipment are very tight, and it is impossible to put down the entire Chinese character library. It is necessary to re-encode the Chinese character information used in the device. This part of the function ucGUI module support is relatively weak.

The third is about windows and controls. Using ucGUI to build a window not only requires manual construction of a series of resource tables, but also has disadvantages such as cumbersome implementation of interface programs, unsightly, and difficulty in implementing many specific application functions.

In-depth analysis of the specific implementation of the ucGUI module, and comprehensive weighing of time factors and product requirements, our team made a careful decision: refactoring the ucGUI module.

6.7.2 Anatomy of ucGUI

The premise of reconstruction is to analyze the ucGUI module as a whole. ucGUI is an efficient, can cut GUI software module, is a relatively lightweight software module, mainly used in embedded systems. I remember that after reading the ucGUI code, I drew an architecture diagram as follows:
Insert picture description here
ucGUI is simply divided into three layers: driver layer, GUI library and window management module.

The bottom layer is the driver layer, which contains multiple modules:

  1. ucGui supports three LCD hardware systems: simple-bus, full-bus and none-bus, and then builds a unified LCD driver interface based on these three hardware.
  2. ucGui includes an OS abstraction layer, which enables it to support multiple operating systems, even including window platform emulation, and also supports a multitasking environment.
  3. ucGUI supports point input devices (mainly including mouse and touch screen) and keyboards, both of which have a two-layer structure. The upper layer is the General layer, which is used to provide services for applications, and the lower layer is the Driver Layer, which implements hardware drivers.

Based on the various packaging interfaces provided by the driver layer, ucGUI builds a GUI library, which contains multiple sub-modules such as color, font, bitmap, and 2Dlibary, which form the core of ucGUI.

The top layer is the window management module, which provides window and control support for the application. The window manager is a cut-down module that organizes the LCD screen in a window mode to simplify the interface program. Based on the window manager, ucGUI also provides support for controls and dialog boxes.

In order to support the window manager module, the ucGUI module additionally provides an interesting memdev module, which provides a memory device mapping mechanism, which is mainly used to optimize screen drawing. The memdev module design is more exquisite. In order to make ucGUI suitable for embedded systems with smaller memory, memdev supports Banding Memory Device. The entire interface is drawn in one drawing. In addition, in order to improve the drawing efficiency, Auto Device Object is supported, and the actual area that needs to be drawn is dynamically calculated each time the drawing is performed, and then the drawing operation is performed.

6.7.3 Refactoring the GUI module

The ucGUI module is an excellent embedded software module, and many design concepts are eye-opening. Unfortunately, excellence is not the same as being applicable. In order to adapt to a wider range of applications, the ucGUI module has many mismatches with our relay protection equipment. Optimizing and iterating these mismatch points has become the starting point for us to refactor the GUI module.

We mainly optimized the ucGUI module as follows:

  1. Simplify the LCD driver layer. No longer distinguish between multiple LCD types, and consider the needs of distributed liquid crystal modules, etc., to rebuild the LCD drive interface.
  2. Combined with the dynamic execution framework, the GUI task is restricted to be executed in a single task environment. This strategy makes the interface program need not consider issues such as mutual exclusion locks, and simplifies the entire GUI software module.
  3. Combining the features of the microcomputer to protect the monochrome LCD, simplify the GUI core modules, including color, font, bitmap, 2DLibary and other sub-modules.
  4. Rewrite the windows manager module, increase the jump mechanism between windows, remove the window clipping mechanism, and optimize the controls.
  5. Increase the configuration software support, not only to support the interface drawing function, but also to collect and sort all the string information used in the system, and re-encode, and then uniformly generate the interface resource file.
  6. Remove the memdev module and internalize it to the driver layer.
  7. ……

After a series of adjustments, the GUI architecture is shown in the following figure: the
Insert picture description here
entire GUI module is divided into three layers, the lowest layer is the driver abstraction layer, which is convenient for hardware transplantation. Currently, only three types of drivers are considered: LCD, key, and touch screen. Above the driver abstraction layer is the basic support environment for GUI, which mainly includes four parts: color, font, bitmap, and 2d Libary. The interface is similar to ucGUI, but it is optimized based on black and white monochrome LCD. Above the basic support environment is the window management system, which mainly includes three parts: "controls, window management structure", "node structure information", and "node execution environment".

Below the GUI module is mainly the specific realization of various drivers, and above the GUI module is the specific application program, which is mainly manifested as the specific message response function of windows and controls, similar to VB programming.

◇◇◇

It may be to support more LCD devices. The LCD driver layer of ucGUI is more complicated and has more hierarchical structure. But even so, our needs still cannot be met. As mentioned in the previous distributed model, the human-machine interface will be distributed to another CPU, at this time the interface provided by ucGUI is not suitable.

How to build a more suitable driver interface? The memdev module of ucGUI provides us with inspiration. Since it is possible to draw based on memory, why not use the entire mapped memory area as an LCD drawing driver interface! Based on this concept, the optimized LCD driver interface is as follows:

/* 获取液晶内存映射缓冲区,该缓冲区由驱动程序维护 */
BYTE *hwGetLcdMap(void);

/* 整屏数据输出 */
void hwOutputAllLCD(void);
	
/*
 *  Description: LCD带状数据输出
 *  Input: 
 *    DWORD y0, y1: 位置
 *  Others: 范围(y0 <= y1 <= range)
 */
void hwOutputBandLCD(DWORD y0, DWORD y1);

/*
 *  Description: 块状数据输出
 *  Input: 
 *    DWORD x0,y0,x1,y1: 矩阵
 *  Return: 成功返回TRUE,否则返回FALSE
 *  Others: 范围(y0 < y1 <= range, x0 < x1 <= range)
 */
void hwOutputBlockLCD(DWORD x0, DWORD y0, DWORD x1, DWORD y1);

With this interface mode, not only is the traditional LCD driver easy to write, but if the LCD interface needs to be distributed to other CPUs, it is only necessary to transfer the LCD mapped memory to other CPUs in the driver.

In a distributed system, if the LCD dot matrix is ​​large, it takes more time to transmit the entire dot matrix data, which may affect the LCD interface key experience. At this time, various compression strategies can be added to the driver, such as classic RLE (Run-Length Encoding) encoding, or strategies such as pre-transmitting static information such as strings. In short, the problem is restricted to a single point in the driver layer.

Using the LCD interface based on memdev, the memdev module in the ucGUI module is naturally omitted, which helps to further simplify the ucGUI program structure.

◇◇◇

When using the ucGUI module, the biggest pain point is slowness. Not only is the window drawing slow, but the user's button response is also slow, resulting in a poor user experience. Thanks to various early program dynamic execution architectures, we have measures to analyze in detail where the blocking points of the ucGUI module are, and finally locate the window clipping and drawing mechanism of ucGUI.

In order to complete the drawing of multiple stacked windows, ucGUI needs to divide the entire liquid crystal window into multiple rectangular areas, and then draw them in sequence. Assuming that there are two overlapping windows on the desktop window, the coordinates are (10, 10, 109, 109) and (50, 50, 149, 149). At this time, the entire LCD window is divided into multiple rectangular cropping areas, as shown in the figure below. The color window shows:

Insert picture description here
The coordinates are listed as follows:

1.(0,0,319,9)
2.(0,10,9,49)
3.(110,10,319,49)
4.(0,50,9,109)
5.(150,50,319,109)
6.(0,110,49,149)
7.(150,110,319,149)
8.(0,150,319,239)

This strategy has a wide range of applications, but it also leads to low efficiency in drawing the LCD interface. The liquid crystal size of the microcomputer protection device is small and does not require complicated window stacking. How to make full use of the microcomputer to protect the small size of the liquid crystal and further optimize this process?

In the ucGUI module, each window has not only a parent window, but also a sibling window. In order to get rid of the complicated window clipping strategy, we limit all windows to be stacked in the form of parent and child windows. Each window covers the entire LCD interface. At this time, windows are naturally created and cancelled in a stack.

This strategy also helps to improve memory utilization. Build an execution stack to organize all windows, controls, strings and other information uniformly, and table entries are also allocated in the execution stack. When the window is created, all the information required by the window is pre-allocated at one time. After the window is cancelled, all information is released.

The execution stack diagram is as follows:
Insert picture description here
Of course, after adopting this strategy, it will also bring some additional constraints, such as window hiding is not supported, two brother windows cannot be displayed at the same time, and the size of the table must be determined first when the table is initialized. Fortunately, these restrictions are easy to circumvent, but this brings a significant improvement in user experience.

◇◇◇

The entire GUI module is driven by messages. The main process of the GUI module is as follows:

void guiMainLoop(void)
{
	if (有按键消息)
	{
		打开背光灯
		按键消息处理
		return
	}
	else
	{
		if (超时时间到达)
			关闭背光灯
	}
	时间消息处理
}

There are two types of key messages, one is the system recognizes the key message, and the other is the system does not recognize the key message.

  1. For the system that does not recognize the key-press message, the processing flow is relatively simple. The current key-press message is sent directly to the root node. If the upper-level application wants to process the key-press, it only needs to reload the processing function of the root node. This mechanism helps to realize the key functions of specific industries, such as the signal reset key of the microcomputer protection, the opening and closing keys, etc.
  2. The keys recognized by the system are mainly up, down, left, right, OK, cancel and other keys. This type of key is the key used by convention in the GUI module. The processing flow is as follows:
if (存在当前控件)
{
	发送给当前控件
	if (当前控件未处理)
	{
		发送给当前窗口
		if (当前窗口未处理)
		{
			发送给root节点,上层应用可以重载root节点的处理流程.
		}
	}
}

The timing message is registered in the way of registration. When a window is opened and closed, the system timing message function is updated to the current window and the message function list containing the controls, and it is restored to the parent window's timing message function when the window is destroyed.

In addition to timing and button messages, the GUI system also includes other messages:

  1. The window creation message is called after a window and all the controls it contains are created. The user can override this function to complete additional initialization information. In general, this function will be overloaded.
  2. Window undo message, called before a window is about to be undone.
  3. The window redraws the message.
  4. ……

Based on the message system, each interface program is composed of a series of message functions, and the overall structure is as follows:

窗口列表
{
	{窗口ID, 消息函数列表地址, 消息函数个数},
	{窗口ID, 消息函数列表地址, 消息函数个数},
	{窗口ID, 消息函数列表地址, 消息函数个数},
	……
}

窗口A消息函数列表
{
	{控件或窗口ID, 消息类型,消息响应函数},
	{控件或窗口ID, 消息类型,消息响应函数},
	{控件或窗口ID, 消息类型,消息响应函数},
	……
}

消息响应函数A
消息响应函数B
消息响应函数C
……

◇◇◇

In order to improve the user experience, the LCD interface to support the man is the most basic requirement, but it is a pity that the flash resources in many industrial embedded systems are very small, even the most basic 16*16 font library can not fit. At this point, you need to refine all the Chinese character libraries used and re-encode them.

Considering the static organization structure, this part of the work belongs to the category of configuration software. In fact, the configuration software just contains all the string information of each type of microcomputer protection device, and then it is reorganized and coded.

In the same way, each window interface drawing also belongs to the category of configuration software, and then the interface resource file is generated for easy access to the interface program. The drawing part of the LCD interface in the configuration software is shown in the figure below:
Insert picture description here

6.7.4 The relationship between the GUI module and the overall architecture

Due to space limitations, this chapter fails to describe in detail the many details of the GUI module iteration process, but even so, it is easy for everyone to understand the iterative path of the GUI module: demand promotion, continuous adaptive transformation . Time will help us go far, and a set of GUI modules suitable for microcomputer protection has been slowly built by us. Similar to GUI modules, many excellent modules need to be similarly modified when they are introduced.

In the process of building the GUI module, there are many relationships with the overall architecture, such as:

  1. Functions such as LCD interface resources, character string information, and Chinese character recoding require the cooperation of configuration software, and these requirements will further promote the iterative upgrade of configuration software.
  2. On-site users often have some special interface requirements, and adopting a hard-coded strategy will result in many on-site engineering versions. Similar to configuration software, such special interfaces can be organized through maintenance software.
  3. The interface program needs to be repeatedly debugged when writing, and the virtual device driver layer is constructed. Simulation and debugging based on the windows virtual environment can speed up the development progress.
  4. Scripted transformation of function button module.
  5. ……

Therefore, building complex modules will force us to consider the overall situation and further enhance our sense of architecture. If more complex modules are built, we will naturally have the ability to design architecture.

——————————————

Back to Contents

I am Xiaomaer, an embedded software engineer who longs for conscience and soul. Welcome your company and travel. If you are interested, you can add a personal WeChat account nzn_xiaomaer to communicate, and you need to note the word " different dimension ".

Guess you like

Origin blog.csdn.net/zhangmalong/article/details/106864758