矩陣鍵盤

背景

移植矩陣鍵盤。矩陣鍵盤的原理不贅述。

設備樹

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 <stdio.h>
#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,這個具體爲什麼,我還不太清楚。

經過上面的配置,按鍵就可以正常使用了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章