Skip to content

Commit 652f764

Browse files
committed
input: add keyboard matrix driver
Add a generic kmatrix lower-half with polling/debounce, STM32 board adapters, Kconfig options, a public API header, and a test example/documentation. Signed-off-by: Felipe Moura <[email protected]> decouple kbd / keypad. Fix some comments add documentation fix rule issues Update CMakeLists.txt update documentation. improve documentation
1 parent fac7674 commit 652f764

File tree

19 files changed

+1966
-139
lines changed

19 files changed

+1966
-139
lines changed
Lines changed: 1 addition & 0 deletions
Loading

Documentation/components/drivers/character/input/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Input Devices
55
.. toctree::
66
:caption: Supported Drivers
77

8+
keypad-keyboard.rst
89
keypad.rst
910
sbutton.rst
1011

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
=======================
2+
Keyboard/Keypad Drivers
3+
=======================
4+
5+
6+
**Keypads vs. Keyboards** Keyboards and keypads are really the same
7+
devices for NuttX. A keypad is thought of as simply a keyboard with
8+
fewer keys.
9+
10+
**Special Commands**. In NuttX, a keyboard/keypad driver is simply
11+
a character driver that may have an (optional) encoding/decoding
12+
layer on the data returned by the character driver. A keyboard may
13+
return simple text data (alphabetic, numeric, and punctuation) or
14+
control characters (enter, control-C, etc.) when a key is pressed.
15+
We can think about this the "normal" keyboard data stream.
16+
However, in addition, most keyboards support actions that cannot
17+
be represented as text or control data. Such actions include
18+
things like cursor controls (home, up arrow, page down, etc.),
19+
editing functions (insert, delete, etc.), volume controls, (mute,
20+
volume up, etc.) and other special functions. In this case, some
21+
special encoding may be required to multiplex the normal text data
22+
and special command key press data streams.
23+
24+
**Key Press and Release Events** Sometimes the time that a key is
25+
released is needed by applications as well. Thus, in addition to
26+
normal and special key press events, it may also be necessary to
27+
encode normal and special key release events.
28+
29+
**Encoding/Decoding** Layer. An optional encoding/decoding layer
30+
can be used with the basic character driver to encode the keyboard
31+
events into the text data stream. The function interfaces that
32+
comprise that encoding/decoding layer are defined in the header
33+
file ``include/nuttx/input/kbd_code.h``. These functions provide
34+
a matched set of (a) driver encoding interfaces, and (b)
35+
application decoding interfaces.
36+
37+
#. **Driver Encoding Interfaces**. These are interfaces used by
38+
the keyboard/keypad driver to encode keyboard events and data.
39+
40+
- ``kbd_press()``
41+
42+
**Function Prototype:**
43+
44+
**Description:**
45+
46+
**Input Parameters:**
47+
48+
- ``ch``: The character to be added to the output stream.
49+
- ``stream``: An instance of ``lib_outstream_s`` to perform
50+
the actual low-level put operation.
51+
52+
**Returned Value:**
53+
54+
- ``kbd_release()``
55+
56+
**Function Prototype:**
57+
58+
**Description:**
59+
60+
**Input Parameters:**
61+
62+
- ``ch``: The character associated with the key that was
63+
released.
64+
- ``stream``: An instance of ``lib_outstream_s`` to perform
65+
the actual low-level put operation.
66+
67+
**Returned Value:**
68+
69+
- ``kbd_specpress()``
70+
71+
**Function Prototype:**
72+
73+
**Description:**
74+
75+
**Input Parameters:**
76+
77+
- ``keycode``: The command to be added to the output
78+
stream. The enumeration ``enum kbd_keycode_e keycode``
79+
identifies all commands known to the system.
80+
- ``stream``: An instance of ``lib_outstream_s`` to perform
81+
the actual low-level put operation.
82+
83+
**Returned Value:**
84+
85+
- ``kbd_specrel()``
86+
87+
**Function Prototype:**
88+
89+
**Description:**
90+
91+
**Input Parameters:**
92+
93+
- ``keycode``: The command to be added to the output
94+
stream. The enumeration ``enum kbd_keycode_e keycode``
95+
identifies all commands known to the system.
96+
- ``stream``: An instance of ``lib_outstream_s`` to perform
97+
the actual low-level put operation.
98+
99+
**Returned Value:**
100+
101+
#. **Application Decoding Interfaces**. These are user interfaces
102+
to decode the values returned by the keyboard/keypad driver.
103+
104+
- ``kbd_decode()``
105+
106+
**Function Prototype:**
107+
108+
**Description:**
109+
110+
**Input Parameters:**
111+
112+
- ``stream``: An instance of ``lib_instream_s`` to perform
113+
the actual low-level get operation.
114+
- ``pch``: The location to save the returned value. This
115+
may be either a normal, character code or a special
116+
command (i.e., a value from ``enum kbd_getstate_s``.
117+
- ``state``: A user provided buffer to support parsing.
118+
This structure should be cleared the first time that
119+
``kbd_decode()`` is called.
120+
121+
**Returned Value:**
122+
123+
- ``KBD_PRESS`` (0)**: Indicates the successful receipt
124+
of normal, keyboard data. This corresponds to a keypress
125+
event. The returned value in ``pch`` is a simple byte of
126+
text or control data.
127+
- ``KBD_RELEASE`` (1)**: Indicates a key release event.
128+
The returned value in ``pch`` is the byte of text or
129+
control data corresponding to the released key.
130+
- ``KBD_SPECPRESS`` (2)**: Indicates the successful
131+
receipt of a special keyboard command. The returned value
132+
in ``pch`` is a value from ``enum kbd_getstate_s``.
133+
- ``KBD_SPECREL`` (3)**: Indicates a special command key
134+
release event. The returned value in ``pch`` is a value
135+
from ``enum kbd_getstate_s``.
136+
- ``KBD_ERROR`` (``EOF``)**: An error has getting the
137+
next character (reported by the ``stream``). Normally
138+
indicates the end of file.
139+
140+
**I/O Streams**. Notice the use of the abstract I/O streams in
141+
these interfaces. These stream interfaces are defined in
142+
``include/nuttx/streams.h``.
143+
Lines changed: 79 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,83 @@
11
=======================
2-
Keyboard/Keypad Drivers
2+
Matrix Keypad (KMATRIX)
33
=======================
44

5-
**Keypads vs. Keyboards** Keyboards and keypads are really the
6-
same devices for NuttX. A keypad is thought of as simply a
7-
keyboard with fewer keys.
8-
9-
**Special Commands**. In NuttX, a keyboard/keypad driver is simply
10-
a character driver that may have an (optional) encoding/decoding
11-
layer on the data returned by the character driver. A keyboard may
12-
return simple text data (alphabetic, numeric, and punctuation) or
13-
control characters (enter, control-C, etc.) when a key is pressed.
14-
We can think about this the "normal" keyboard data stream.
15-
However, in addition, most keyboards support actions that cannot
16-
be represented as text or control data. Such actions include
17-
things like cursor controls (home, up arrow, page down, etc.),
18-
editing functions (insert, delete, etc.), volume controls, (mute,
19-
volume up, etc.) and other special functions. In this case, some
20-
special encoding may be required to multiplex the normal text data
21-
and special command key press data streams.
22-
23-
**Key Press and Release Events** Sometimes the time that a key is
24-
released is needed by applications as well. Thus, in addition to
25-
normal and special key press events, it may also be necessary to
26-
encode normal and special key release events.
27-
28-
**Encoding/Decoding** Layer. An optional encoding/decoding layer
29-
can be used with the basic character driver to encode the keyboard
30-
events into the text data stream. The function interfaces that
31-
comprise that encoding/decoding layer are defined in the header
32-
file ``include/nuttx/input/kbd_code.h``. These functions provide
33-
an matched set of (a) driver encoding interfaces, and (b)
34-
application decoding interfaces.
35-
36-
#. **Driver Encoding Interfaces**. These are interfaces used by
37-
the keyboard/keypad driver to encode keyboard events and data.
38-
39-
- ``kbd_press()``
40-
41-
**Function Prototype:**
42-
43-
**Description:**
44-
45-
**Input Parameters:**
46-
47-
- ``ch``: The character to be added to the output stream.
48-
- ``stream``: An instance of ``lib_outstream_s`` to perform
49-
the actual low-level put operation.
50-
51-
**Returned Value:**
52-
53-
- ``kbd_release()``
54-
55-
**Function Prototype:**
56-
57-
**Description:**
58-
59-
**Input Parameters:**
60-
61-
- ``ch``: The character associated with the key that was
62-
released.
63-
- ``stream``: An instance of ``lib_outstream_s`` to perform
64-
the actual low-level put operation.
65-
66-
**Returned Value:**
67-
68-
- ``kbd_specpress()``
69-
70-
**Function Prototype:**
71-
72-
**Description:**
73-
74-
**Input Parameters:**
75-
76-
- ``keycode``: The command to be added to the output
77-
stream. The enumeration ``enum kbd_keycode_e keycode``
78-
identifies all commands known to the system.
79-
- ``stream``: An instance of ``lib_outstream_s`` to perform
80-
the actual low-level put operation.
81-
82-
**Returned Value:**
83-
84-
- ``kbd_specrel()``
85-
86-
**Function Prototype:**
87-
88-
**Description:**
89-
90-
**Input Parameters:**
91-
92-
- ``keycode``: The command to be added to the output
93-
stream. The enumeration ``enum kbd_keycode_e keycode``
94-
identifies all commands known to the system.
95-
- ``stream``: An instance of ``lib_outstream_s`` to perform
96-
the actual low-level put operation.
97-
98-
**Returned Value:**
99-
100-
#. **Application Decoding Interfaces**. These are user interfaces
101-
to decode the values returned by the keyboard/keypad driver.
102-
103-
- ``kbd_decode()``
104-
105-
**Function Prototype:**
106-
107-
**Description:**
108-
109-
**Input Parameters:**
110-
111-
- ``stream``: An instance of ``lib_instream_s`` to perform
112-
the actual low-level get operation.
113-
- ``pch``: The location to save the returned value. This
114-
may be either a normal, character code or a special
115-
command (i.e., a value from ``enum kbd_getstate_s``.
116-
- ``state``: A user provided buffer to support parsing.
117-
This structure should be cleared the first time that
118-
``kbd_decode()`` is called.
119-
120-
**Returned Value:**
121-
122-
- ``KBD_PRESS`` (0)**: Indicates the successful receipt
123-
of normal, keyboard data. This corresponds to a keypress
124-
event. The returned value in ``pch`` is a simple byte of
125-
text or control data.
126-
- ``KBD_RELEASE`` (1)**: Indicates a key release event.
127-
The returned value in ``pch`` is the byte of text or
128-
control data corresponding to the released key.
129-
- ``KBD_SPECPRESS`` (2)**: Indicates the successful
130-
receipt of a special keyboard command. The returned value
131-
in ``pch`` is a value from ``enum kbd_getstate_s``.
132-
- ``KBD_SPECREL`` (3)**: Indicates a special command key
133-
release event. The returned value in ``pch`` is a value
134-
from ``enum kbd_getstate_s``.
135-
- ``KBD_ERROR`` (``EOF``)**: An error has getting the
136-
next character (reported by the ``stream``). Normally
137-
indicates the end of file.
138-
139-
**I/O Streams**. Notice the use of the abstract I/O streams in
140-
these interfaces. These stream interfaces are defined in
141-
``include/nuttx/streams.h``.
5+
**What is a Keypad?**
6+
A keypad is a small keyboard with a limited set of keys, typically
7+
arranged in a matrix. It is commonly used for numeric input, access
8+
control, or simple user interfaces.
9+
10+
For example, a typical 12-key numeric keypad looks like this:
11+
12+
.. image:: images/keypad-example.png
13+
:alt: Example of a 12-key matrix keypad
14+
:align: center
15+
:width: 200px
16+
17+
**Purpose**. The KMATRIX driver provides a generic keypad
18+
implementation for boards that expose a switch matrix through GPIOs.
19+
It periodically scans rows and columns, detects state changes with a
20+
simple debounce, and emits keyboard events through the common keyboard
21+
upper-half. This makes the device available as a character driver
22+
(e.g., ``/dev/keypad0``) using the standard keyboard
23+
interfaces.
24+
25+
**Why Polling**. This first version uses polling to be broadly usable
26+
on any board with available GPIOs, without requiring per-board IRQ
27+
wiring, pin interrupt capabilities, or expander-specific interrupt
28+
support. Polling also simplifies early bring-up and makes the driver
29+
predictable while the keymap and GPIO configuration are validated.
30+
Future iterations are expected to add interrupt-driven scanning and
31+
I2C expander variants; the GPIO polling path remains a good baseline
32+
and fallback.
33+
34+
**Driver Overview**. The KMATRIX lower-half scans the matrix and calls
35+
``keyboard_event()`` when it detects a press or release. The keyboard
36+
upper-half registers the character device at the requested ``devpath``
37+
and stores events in a circular buffer. Applications read
38+
``struct keyboard_event_s`` from the device or use the optional
39+
kbd-codec layer.
40+
41+
**Board Support**. To support KMATRIX, a board must provide:
42+
43+
#. **GPIO Definitions**
44+
45+
- Define the row and column GPIOs (arrays of pins).
46+
- Provide a keymap array indexed by ``row * ncols + col``.
47+
48+
#. **Configuration Callbacks**
49+
50+
- ``config_row(pin)``: Configure a row GPIO as output.
51+
- ``config_col(pin)``: Configure a column GPIO as input with pull-up
52+
or pull-down consistent with the wiring.
53+
- ``row_set(pin, active)``: Drive a row active/inactive. For the
54+
STM32F4Discovery example, rows are driven low to activate.
55+
- ``col_get(pin)``: Read a column and return ``true`` when pressed.
56+
57+
#. **Registration Hook**
58+
59+
- Implement ``board_kmatrix_initialize(const char *devpath)`` to
60+
call ``kmatrix_register(&config, devpath)``.
61+
- Invoke the board hook during bring-up (for example,
62+
``board_kmatrix_initialize("/dev/keypad0")``).
63+
64+
**Reference Implementation (STM32F4Discovery)**. The current reference
65+
is in ``boards/arm/stm32/common/src/stm32_kmatrix_gpio.c``:
66+
67+
- Rows: ``BOARD_KMATRIX_ROW0..3`` (outputs)
68+
- Columns: ``BOARD_KMATRIX_COL0..2`` (inputs with pull-up)
69+
- Keymap: 4x3 phone keypad layout
70+
- Callbacks: ``km_stm32_config_row``, ``km_stm32_config_col``,
71+
``km_stm32_row_set``, ``km_stm32_col_get``
72+
- Registration: ``board_kmatrix_initialize()`` calls
73+
``kmatrix_register()``
74+
75+
**Data Path Summary**.
76+
77+
- Board calls ``board_kmatrix_initialize("/dev/keypad0")``
78+
- ``kmatrix_register()`` configures GPIOs and calls
79+
``keyboard_register(&lower, devpath, buflen)``
80+
- The upper-half registers the device node at ``devpath``
81+
- ``kmatrix_scan_worker()`` calls ``keyboard_event()`` on press/release
82+
- Applications read events from the device node
14283

0 commit comments

Comments
 (0)