矩阵键盘

背景

移植矩阵键盘。矩阵键盘的原理不赘述。

设备树

evm的板子上有一个2x3的矩阵键盘,设备树中也有体现。参考这个实现自己的矩阵键盘设备树如下:

    matrix_keypad: matrix_keypad@0 {
        compatible = "gpio-matrix-keypad";
        debounce-delay-ms = <5>;
        col-scan-delay-us = <2>;

        row-gpios = <&gpio3 15 GPIO_ACTIVE_HIGH     /* Bank1, pin15 */
                 &gpio3 21 GPIO_ACTIVE_HIGH     /* Bank1, pin21 */
                 &gpio1 27 GPIO_ACTIVE_HIGH     /* Bank1, pin27 */
                 &gpio1 25 GPIO_ACTIVE_HIGH>;   /* Bank1, pin25 */

        col-gpios = <&gpio1 23 GPIO_ACTIVE_HIGH     /* Bank1, pin23 */
                &gpio1 21 GPIO_ACTIVE_HIGH         /* Bank1, pin21 */
                &gpio1 26 GPIO_ACTIVE_HIGH         /* Bank1, pin26 */
                &gpio1 24 GPIO_ACTIVE_HIGH         /* Bank1, pin24 */
                &gpio1 22 GPIO_ACTIVE_HIGH         /* Bank1, pin22 */
                &gpio1 20 GPIO_ACTIVE_HIGH         /* Bank1, pin20 */
                &gpio1 19 GPIO_ACTIVE_HIGH         /* Bank1, pin19 */
                &gpio1 17 GPIO_ACTIVE_HIGH         /* Bank1, pin17 */
                &gpio1 18 GPIO_ACTIVE_HIGH         /* Bank1, pin18 */
                &gpio1 16 GPIO_ACTIVE_HIGH>;         /* Bank1, pin16 */

        linux,keymap = <0x0000003b      /* F1 */
                0x00010010      /* Q */
                0x0002001e      /* A */
                0x0003002c      /* Z */
                0x00040002      /* 1 */
                0x00050005      /* 4 */
                0x00060008      /* 7 */
                0x0007000c      /* MINUS */
                0x0008001c      /* ENTER */
                0x0009003f      /* F5 */
                0x0100003c      /* F2 */
                0x01010011      /* W */
                0x0102001f      /* S */
                0x0103002d      /* X */
                0x01040003      /* 2 */
                0x01050006      /* 5 */
                0x01060009      /* 8 */
                0x0107000b      /* 0 */
                0x01080001      /* ESC */
                0x01090040      /* F6 */
                0x0200003d      /* F3 */
                0x02010012      /* E */
                0x02020020      /* D */
                0x0203002e      /* C */
                0x02040004      /* 3 */
                0x02050007      /* 6 */
                0x0206000a      /* 9 */
                0x02070026      /* L */
                0x02080069      /* LEFT */
                0x02090041      /* F7 */
                0x0300003e      /* F4 */
                0x03010013      /* R */
                0x03020021      /* F */
                0x0303002f      /* V */
                0x0304001d      /* LEFTCTRL */
                0x0305002a      /* LEFTSHIFT */
                0x03060067      /* UP */
                0x0307006c      /* DOWN */
                0x0308006a      /* RIGHT */
                0x03090042>;      /* F8 */
    };

&am33xx_pinmux {
    pinctrl-names = "default";
    pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &clkout2_pin>;

    matrix_keypad_s0: matrix_keypad_s0 {
        pinctrl-single,pins = <
            0x64 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a9.gpio1_25 */
            0x6c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a11.gpio1_27 */
            0x194 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.gpio3_15 */
            0x1AC (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.gpio3_21 */

            0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* gpmc_a5.gpio1_16 */
            0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* gpmc_a5.gpio1_17 */
            0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* gpmc_a5.gpio1_18 */
            0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* gpmc_a5.gpio1_19 */
            0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* gpmc_a5.gpio1_20 */
            0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* gpmc_a5.gpio1_21 */
            0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* gpmc_a6.gpio1_22 */
            0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* gpmc_a6.gpio1_23 */
            0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* gpmc_a6.gpio1_24 */
            0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* gpmc_a10.gpio1_26 */
        >;
    };

    ... ...
};

第一部分是设置按键的keymap;第二部分是设置管脚。

keymap

keymap的设置可以参考Documentation/devicetree/bindings/input/matrix-keymap.tx
在这里面可以看到keymap值的计算方式:

row << 24 | column << 16 | key-code

那么key-code又怎么看呢?可以参考Documentation/input/event-codes.txt文档

EV_KEY:
----------
EV_KEY events take the form KEY_<name> or BTN_<name>. For example, KEY_A is used
to represent the 'A' key on a keyboard. When a key is depressed, an event with
the key's code is emitted with value 1. When the key is released, an event is
emitted with value 0. Some hardware send events when a key is repeated. These
events have a value of 2. In general, KEY_<name> is used for keyboard keys, and
BTN_<name> is used for other types of momentary switch events.

可以在内核源码中搜索KEY_A,找到对应的宏定义。可以参看arch/arm/boot/dts/include/dt-bindings/input/input.h。

小工具

知道了keymap的是如何计算的,但是这么多按键,一个个的算,太麻烦,写个小程序。

#include 
#include "input.h"

typedef struct {
    char *name;
    int key_val;
}key_map_t;


key_map_t keys[] = {
    {"F1", KEY_F1}, 
    {"F2", KEY_F2}, 
    {"F3", KEY_F3}, 
    {"F4", KEY_F4}, 
    {"Q", KEY_Q},   
    {"W", KEY_W},   
    {"E", KEY_E},   
    {"R", KEY_R},   
    {"A", KEY_A},   
    {"S", KEY_S},   
    {"D", KEY_D},   
    {"F", KEY_F},   
    {"Z", KEY_Z},   
    {"X", KEY_X},   
    {"C", KEY_C},   
    {"V", KEY_V},   
    {"1", KEY_1},   
    {"2", KEY_2},   
    {"3", KEY_3},   
    {"LEFTCTRL", KEY_LEFTCTRL}, 
    {"4", KEY_4},   
    {"5", KEY_5},   
    {"6", KEY_6},   
    {"LEFTSHIFT", KEY_LEFTSHIFT},   
    {"7", KEY_7},   
    {"8", KEY_8},   
    {"9", KEY_9},   
    {"UP", KEY_UP}, 
    {"MINUS", KEY_MINUS},   
    {"0", KEY_0},   
    {"L", KEY_L},   
    {"DOWN", KEY_DOWN}, 
    {"ENTER", KEY_ENTER},   
    {"ESC", KEY_ESC},   
    {"LEFT", KEY_LEFT}, 
    {"RIGHT", KEY_RIGHT},   
    {"F5", KEY_F5}, 
    {"F6", KEY_F6}, 
    {"F7", KEY_F7}, 
    {"F8", KEY_F8}, 
    {NULL, 0},
};

#define MAX_ROW_NUM 4
#define MAX_COL_NUM 10

int main()
{
    int row = 0; 
    int col = 0;
    int val = 0;
    int code = 0;
    char *name = NULL;

    for (row = 0; row < MAX_ROW_NUM; row++) {
        for (col = 0; col < MAX_COL_NUM; col++) {
            name = keys[row+col*4].name;
            code = keys[row+col*4].key_val;
            val = MATRIX_KEY(row, col, code);   
            printf("0x%08x  /* %s */\n", val, name);
        }
    }

    return 0;
}

此处的input.h,就是刚才找到的input.h,直接拷贝到当前目录。然后编译,执行就可以得到如下类似的内容。

0x0000003b      /* F1 */

配置管脚

如何配置管脚

0x64 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a9.gpio1_25 */

就拿gpio1_25举例
PIN_OUTPUT_PULLDOWN
顾名思义,输出下拉。

MUX_MODE7:
在二百多页的文档中搜索gpio1_25,可以在Pin Attributes表中看到该管脚可以有8种模式,而gpio的模式刚好对应的是mode 7。

0x64
在刚才的搜索中可以看到,该管脚的名称是GPMC_A9。在四千多页的文档中搜索GPMC_A9,可以看到864h conf_gpmc_a9这行。864h,这个数就是咱们要找的,但不是最终的。还需要减去0x800,这个具体为什么,我还不太清楚。

经过上面的配置,按键就可以正常使用了。

你可能感兴趣的:(AM335x,AM335x移植)