In-depth understanding of the AMetal framework, the universal button interface can not be ignored

Prof. Zhou Ligong's new book "Programming for AMetal Frameworks and Interfaces (Part 1)" introduces the AMetal framework in detail. By reading this book, you can learn highly multiplexed software design principles and development ideas for interface programming. Focus on your own "core domain", change your own programming thinking, and achieve common progress between the company and the individual. Authorized by Professor Zhou Ligong, from now on, the Zhiyuan Electronic Public Number will serialize the contents of the book, and is willing to share it.

The eighth chapter is to understand AMetal in depth . The content of this article is 8.5 universal button interface.

8.5 Universal button interface

> > > 8.5.1 Defining interfaces

1. Interface naming

Since the object of operation is a key, the key is an input device. In order to make the meaning clearer, the interface name is increased by the input keyword. Therefore, the interface name is prefixed with "am_input_key_".

The operation of the buttons is mainly divided into two parts: button detection and button processing. The button detection is related to the specific hardware, and the button processing is related to the application and is completed by the user.

For the user, it only needs to care about how to handle the button, and then define the corresponding button processing method (function), do not need to care about the specific details of the button detection.

For button detection, it only needs to detect whether a button event occurs (button press or button release). When a button event is detected, the user should be notified to perform related button processing.

Obviously, the button processing method is defined by the user, and only the user knows that the button detection module is unknown. When a key event is detected, in order to be able to execute the corresponding key processing method, the key detection module must be called to the corresponding key processing method by some method.

It can be seen that the key processing method is defined by the user, but needs to be called by the key detection module, and can be handled by a typical callback mechanism, that is, the key processing method is regarded as a function that needs to be called back by the key detection module. The user registers the key processing function into the key detection module (passing the function address to the key processing module, the key processing module uses the function pointer to save it), and when detecting the key event, searching for the key processing function already registered in the module, Then call one by one (called by function pointer).

Although the key management can be realized by using a single callback mechanism, the responsibility of the key detection module is not limited. It not only handles the key detection related to the hardware, but also manages the callback function registered by the user, which is contrary to the single responsibility. in principle.

Based on the essence of the button detection module: detecting button events. The part that manages the user registration callback function can be separated to form a separate button management module.

Based on this, the user no longer directly interacts with the button detection module, and the user registers the button processing method into the button management module. When the button detection module detects the button event, the button management module is notified to notify that a button event occurs, and after receiving the notification, the button management module searches for the button processing function already registered in the module, and then calls one by one.

It can be seen that after the button management module is added, the user and the button detection only interact with the button management module, thereby realizing complete separation between the user and the button detection. This is the typical layered design idea. The user belongs to the application layer, the button management module belongs to the middle layer, and the button detection belongs to the hardware layer. The schematic diagram is shown in Figure 8.14. The middle layer completely isolates the application layer from the hardware layer.

Figure 8.14 Layered structure of the button system

The middle layer needs to provide an interface for the application layer to register key processing functions. The interface name is defined as:

Am_input_key_handler_register

At the same time, the middle layer also needs to provide an interface for the hardware layer to report the key event, and is used to notify the middle layer that a key event occurs when the key event is detected, so that the middle layer calls the key processing function registered by the user. Its interface name is defined as:

Am_input_key_report

2. Interface parameter

To register a key handler with the am_input_key_handler_register() interface, you must first define the type of key handler.

In AMetal, the first parameter of the callback function is generally set to the p_arg parameter of the void * type. When the user registers the callback function, a variable of type void* is specified as the actual argument passed to the first parameter when the callback function is called. Parameters to handle some user-defined context data in the callback function.

In addition, there may be multiple buttons in the system. In order to allow the user to distinguish the buttons so that different buttons can be processed differently, each button can be assigned a unique code key_code. The encoding is an integer, such as 0, 1, 2... For readability, you can use macros to define some common key encodings, such as the corresponding PC keyboard, you can define KEY_A ~ KEY_Z (letter key), KEY_0 ~ KEY_9 (number key), KEY_KP0 ~ KEY_KP9 (keypad number key), etc., the key code is defined in the am_input_code.h file, as defined in KEY_0 ~ KEY_9, see Listing 8.37.

Listing 8.37 Example of key encoding definition (am_input_code.h)

In this way, the application can directly use the meaningful key encoding macro without paying attention to its corresponding specific encoding value, which not only increases the readability of the application, but also makes the application independent of the specific encoding value. More conducive to cross-platform reuse. For example, in an application, it uses the number key 0. In the current platform, the key code value corresponding to the number key 0 is 11, and if in another platform, the code value of the number key 0 is 12. If the current application is implemented using the macro KEY_0 corresponding to the numeric key 0, the application does not need to be modified after the platform is replaced; however, if the application directly uses the encoded value 11, the program needs to be modified after the platform is replaced, and the encoded value is Changed to 12.

Although in most cases only the button press event needs to be handled, as a general-purpose interface, it is also necessary to consider that in some special applications, it may be necessary to handle the button release event. To this end, a button state can be used. The key_state parameter. Since key_state is only used to indicate press or release, the possible values ​​can be defined in the form of macros, defined as follows (am_input.h):

The callback function acts as a button handler and does not need to feed back any information to the actual caller (middle layer), so there is no need to return a value. Based on this, the type of button handler is: no return value, with three parameters: p_arg, key_code, key_state function. The registered callback function needs to use the function pointer to store the address of the function, so that when the key event occurs, the actual key handler is called using the function pointer. The type of the function pointer is defined as:

When registering a key handler, you need to specify the registered key callback function and a void* type p_arg parameter as the first argument to the key handler. The function prototype of am_input_key_handler_register() is:

In practice, the callback function and p_arg need to be stored in memory in order to use them when appropriate. You can define a special struct type to store them, assuming the type is: am_input_key_handler_t (key processor), the specific definition of which is defined later in the implementation. Obviously, every time you register a key callback function, you need to provide such a type of memory space. Therefore, when registering a key handler, you need to specify a button processor space using that type of pointer. The function prototype for am_input_key_handler_register() is:

According to the type of button processing function analyzed in the previous section, when the button management module calls the callback function, it is necessary to know the encoding of the button and the state of the button, so that the application can process according to the actual situation.

Obviously, the key code and the button state need to be detected by the button detection module. When a button event of a certain coded button is detected, the button code and the button state are reported to the button management module, and the button management module calls the button according to the information. Processing function, based on this, when using the am_input_key_report interface to report key events, you need to specify the key encoding key_code and the key state key_state. The function prototype is:

3. return value

The interface has no special description, and directly defines the return value of all interfaces as the standard error number of type int. The complete definition of the button management module interface is shown in Table 8.6. The corresponding class diagram is shown in Figure 8.15.

Figure 8.15 Button Management Interface

Table 8.6 Button Management Common Interface (am_input.h)

> > > 8.5.2 Implementing the interface

1. Implement the am_input_key_handler_register() interface

Since the button manager is a middle-tier module, it is independent of the specific hardware, so the corresponding interface can be directly implemented without defining an abstract method for adapting to different hardware.

When defining interface parameters, it is mentioned that the key handler of type am_input_key_handler_t is used to store the pointer to the callback function and the p_arg parameter of the callback function. For this purpose, the type is defined as:

Obviously, in a system, there may be more than one button processor. For example, the A application needs to process the button coded as KEY_1, and the B application needs to process the button coded as KEY_2, which can define the button processing function to process the respective KEY_1 or KEY_2. Pressing the button, at this point, two button processors are needed to store the button processing functions of the A application and the B application, respectively.

When there are multiple button processors in the system, there is a problem of how to manage. Since the number of button processors is related to the application, the specific number is uncertain. Therefore, the unidirectional linked list is used for management. Add a p_next member to the button handler type to point to the next button handler:

Based on this, the registration key processing function interface can be implemented. The sample program is detailed in Listing 8.38.

Listing 8.38 am_input_key_handler_register() interface implementation example program

The program first determines the validity of the parameters, then completes the assignment of pfn_cb and p_usr_data in the key processor, saves the user's key processing functions and user parameters to the key processor, and then through the 14-15 rows of Listing 8.38. The 2-line code adds the new button processor to the list header. The global variable __gp_handler_head points to the list header. Initially, since no button handler is registered, its value is NULL.

2. Implement the am_input_key_report() interface

The interface is used to report a button event through the interface when the hardware layer detects a button event. When receiving the reported event, it is necessary to traverse all the key processors in the current system and call their key processing functions one by one. The sample program for implementing the key event reporting interface based on this is detailed in Listing 8.39.

Listing 8.39 am_input_key_report() interface implementation example program

The program starts from the head node of the linked list, traverses each button processor in turn, and then calls the button processing function through the function pointer. When the button processing function is called, the user parameter p_usr_data stored in the button processor is used as the button processing function. User parameter passing, key_code and key_state directly use the reported key code and button status.

As an example, the above program is very simple to implement. Unlike other implementations of common interfaces, there is no abstract method defined here. The two interfaces are directly implemented by short code. This is because the button manager itself is Based on the idea of ​​layered design, it does not depend on the specific hardware. It provides an am_input_key_report() interface for the specific hardware detection module to report key events.

For ease of reference, the contents of the button management interface file (am_input.h) are shown in Listing 8.40.

Listing 8.40 am_input.h file contents

> > > 8.5.3 Detection button implementation

The interface of the button manager is implemented above, and the button manager serves as an intermediate layer, which provides an interface for registering key processing functions for the upper layer application, and provides a reporting interface for key events for the lower layer hardware driver. Obviously, for different hardware, the method of button scanning is different, but when scanning the button event, only need to call the am_input_key_report() interface to report the button event.

This section takes a separate keyboard as an example to describe the specific implementation method of the hardware layer detection button. According to the object-oriented design idea, the independent keyboard is treated as an object, and its type is defined as: am_key_gpio_t. which is:

What members do you need to include? In order to realize the automatic scanning of the button timing, a software timer is needed, and a software timer timer member can be added; in the scanning process, in order to achieve the debounce, the key value of the current scan needs to be compared with the key value obtained in the previous scan. Added a key_prev member to save the last scanned key value; when a valid scan key value is detected (the key value obtained in this scan is the same as the key value obtained in the previous scan), it needs to be valid last time. The scan key values ​​are compared to determine which key states have changed, and a key_press member can be added to hold the last valid scan key value. The type of standalone keyboard can be defined as:

Am_key_gpio_t is a standalone keyboard device class. With this type, you can use this type to define an independent keyboard device instance, namely:

In addition, in order to use the independent keyboard normally, you need to know some basic hardware-related information, such as pin information, level information of the button press (high or low level pressed), and the number of buttons. Specifying the time interval for a keyboard scan, that is, the timing period of the software timer, determines how fast the keyboard scans. The information type that can define a separate keyboard is:

In particular, when a button event is detected, the button event needs to be reported using am_input_key_report(). The button event includes the code of the button and the state of the button. The state of the button (press or release) can be determined by the key value of the button scan. . In order to facilitate the user to distinguish between different buttons, the unique code value assigned to each button is equivalent to the unique ID number, so the code value of the button can only be determined by the user. The button scan program cannot be determined, in order to use the correct button event. The encoding needs to provide the encoding information of each button by the user. To this end, in the information of the independent keyboard, the p_codes member is added to point to the encoding information of the button, and the complete independent keyboard information type is defined as:

The AM824-Core has an independent button on the board. When J14's 1 and 2 are shorted, KEY is connected to PIO_KEY (PIO0_1). Assuming that the key assigned to it is uniquely encoded as KEY_KP0, the information for the standalone keyboard can be defined as:

Similarly, in the device type of the stand-alone keyboard, it is necessary to maintain a pointer to the independent keyboard information so that the relevant information can be retrieved from the independent keyboard device at any time. The complete independent keyboard device type is defined as:

Obviously, in order for the button to scan normally, it is necessary to complete the assignment of each member in the device. After the initial assignment is completed, the software timer can be started, and the button is automatically scanned at the scan interval specified in the device information. This work is usually done in the driver's initialization function, and the prototype that defines the initialization function is:

Where p_dev is a pointer to an instance of the am_key_gpio_t type and p_info is a pointer to the instance information of the am_key_gpio_info_t type. Based on the device instance and instance information defined above, the call form is as follows:

An example of the implementation of the initialization function is shown in Listing 8.41.

Listing 8.41 Example of a stand-alone keyboard initialization function implementation

The program first determines the validity of the parameter. It is important to note that since the current device uses the uint32_t type data storage scan key value (such as key_prev, key_press), it can only support up to 32 keys, so when the number of keys exceeds At 32 o'clock, the error number "Unsupported" is returned. If you want to support more independent buttons, you can use a wider data type, but in fact, each button needs to occupy one pin for each button, often the number of independent buttons is not too much, when there are a large number of buttons, often Use a matrix keyboard.

Then, according to the level when the button is pressed, the pin is configured for the input mode, and key_prev and key_press are initially assigned to the corresponding key values ​​when all the keys are not pressed. Finally, the software timer is initialized and started, the timing period of the software timer is set to the scan time interval in the independent keyboard information, and the periodic callback function of the software timer is set to __key_gpio_timer_cb, that is, the independent keyboard is completed in the function. For the implementation of the scan, see Listing 8.42.

Listing 8.42 Independent keyboard scan function implementation

First, the __key_val_read() function is used to read the current scan key value. In the implementation of the __key_val_read() function, the pin levels corresponding to the respective keys are sequentially read, and the level information of each pin is saved in the corresponding In the bit. The currently scanned key value is stored in key_value.

Then compare the key_value with the last scan key value p_dev->key_prev. If the two are equal, it indicates that the scan key value key_value is a valid key value. At this time, the valid key value key_value is compared with the last valid scan key value p_dev->key_press. If the two are not equal, it indicates that a key event occurs, and an XOR operation is used to find a bit that changes between the two. Its value is stored in key_change.

Then, the bits of the key_change are traversed. If the corresponding bit of the key_change is 1, it indicates that the change of the state of the corresponding button needs to be reported. The button bit value and active_low together determine the state of the current button (pressed or not pressed), and its corresponding truth table is shown in Table 8.7. It can be seen that when the value of the key scan is equal to active_low, it indicates that the current key is not in the pressed state. This state change is caused by the release of the key, and the key release event should be reported. On the contrary, it indicates that the current button is in the pressed state. This state change is caused by the button press, and the button press event should be reported. When an event is reported, the key code is obtained from the code information in the independent keyboard information. Note that before the comparison, they are subjected to two "no" operations, "!!", ensuring that the value to be compared can only be 0 or 1.

Table 8.7 Button Status Truth Table

After the end of all key event reporting, it indicates that the processing of a valid scan key value is completed, and the last valid scan key value p_dev->key_press needs to be updated as key_value. Regardless of whether the key value of the valid button changes, the last scan key value p_dev->key_prev is updated at the end of the program for the scan key value key_value.

For ease of reference, a stand-alone keyboard interface file (am_key_gpio.h) is shown as shown in Listing 8.43.

Listing 8.43 am_key_gpio.h file contents

Semiconductor Plastic Package

Semiconductor Plastic Package.Refers to the material whose conductivity is between the conductor and the insulator at room temperature. Semiconductors have a wide range of applications in radios, televisions, and temperature measurement. Diodes are semiconductor devices. Semiconductor refers to a material whose conductivity can be controlled and can range from insulator to conductor. Regardless of technology or economic development, the importance of semiconductors is enormous. Most of today`s electronic products, such as computers, mobile phones or digital recorders, have core units that are very closely related to semiconductors. The common semiconductor materials are silicon, germanium, gallium arsenide, etc., and silicon is a kind of most influential one among various semiconductor materials in commercial applications.

Semiconductor Plastic Package,Semiconductor Package,Silicon Transistor,Bi Directions Thyristor

YANGZHOU POSITIONING TECH CO., LTD. , https://www.pst-thyristor.com

Posted on