mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #18733 from bergzand/pr/driver/matrix_keypad
matrix_keypad: Add matrix-style keypad module
This commit is contained in:
commit
2a934c9434
@ -109,6 +109,7 @@ rsource "lsm303dlhc/Kconfig"
|
||||
rsource "lsm303agr/Kconfig"
|
||||
rsource "ltc4150/Kconfig"
|
||||
rsource "mag3110/Kconfig"
|
||||
rsource "matrix_keypad/Kconfig"
|
||||
rsource "mhz19/Kconfig"
|
||||
rsource "mma8x5x/Kconfig"
|
||||
rsource "mma7660/Kconfig"
|
||||
|
228
drivers/include/matrix_keypad.h
Normal file
228
drivers/include/matrix_keypad.h
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Koen Zandberg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_matrix_keypad Matrix Keypad
|
||||
* @ingroup drivers_sensors
|
||||
* @brief Matrix keypad driver for row/column keypads
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
*
|
||||
* @author Koen Zandberg <koen@bergzand.net>
|
||||
*
|
||||
* This module implements a simple matrix keypad driver where keys are connected
|
||||
* between GPIO columns and rows. It works best with diodes in series with the
|
||||
* switches to prevent key ghosting, but it can be used without these diodes.
|
||||
* @ref CONFIG_MATRIX_KEYPAD_ROWS_USE_OPEN_DRAIN can be enabled when the keypad
|
||||
* doesn't use diodes in the switches.
|
||||
*
|
||||
* The keypad works by configuring the column GPIOs as input with pull-ups. Each
|
||||
* row is configured as open drain with pull-up. One by one the rows are set to
|
||||
* pull their output low. For each row the column GPIOs are read and the state
|
||||
* is checked. When a key is pressed the column GPIO of that switch will read
|
||||
* low as soon as the row it is on is pulled low.
|
||||
*
|
||||
* The debouncing algorithm is a pattern style debounce where the switch must be
|
||||
* in one position for a number of samples, then a set of "don't care" samples
|
||||
* and then in the other position for a number of samples. The samples in the
|
||||
* middle allow for a period where the switch can be either low or high without
|
||||
* affecting the transition. The exact pattern is determined by
|
||||
* @ref CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_BEGIN and
|
||||
* @ref CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_END. These are used as mask where
|
||||
* the switch must be in a determined state. The bits where neither pattern is
|
||||
* set is used as the "don't care" set of samples.
|
||||
*
|
||||
* A full scan of the matrix keypad is done via the @ref matrix_keypad_scan
|
||||
* function. This function iterates over all rows and columns to update the
|
||||
* stored history of every pin.
|
||||
*
|
||||
* When a state change is detected on a switch, the @ref matrix_keypad_cb_t
|
||||
* callback is called with the row and column number together with the new state
|
||||
* of the switch (pressed or not pressed).
|
||||
*/
|
||||
|
||||
#ifndef MATRIX_KEYPAD_H
|
||||
#define MATRIX_KEYPAD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "periph/gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Maximum number of rows
|
||||
*/
|
||||
#ifndef CONFIG_MATRIX_KEYPAD_NUM_ROWS
|
||||
#define CONFIG_MATRIX_KEYPAD_NUM_ROWS 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Maximum number of columns
|
||||
*/
|
||||
#ifndef CONFIG_MATRIX_KEYPAD_NUM_COLUMNS
|
||||
#define CONFIG_MATRIX_KEYPAD_NUM_COLUMNS 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debounce pattern high to low bits
|
||||
*
|
||||
* This pattern should consist of bits set on the most significant bits of the
|
||||
* value. The number of bits set determines the number of scans the key must be
|
||||
* in the current state before a change is processed.
|
||||
*/
|
||||
#ifndef CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_BEGIN
|
||||
#define CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_BEGIN 0xC0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debounce pattern low to high bits
|
||||
*
|
||||
* This pattern should consist of bits set on the least significant bits of the
|
||||
* value. The number of bits set determines the number of scans the key must be
|
||||
* in the next state before a change is processed.
|
||||
*/
|
||||
#ifndef CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_END
|
||||
#define CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_END 0x7
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Use open drain GPIO mode
|
||||
*/
|
||||
#ifndef CONFIG_MATRIX_KEYPAD_ROWS_USE_OPEN_DRAIN
|
||||
#define CONFIG_MATRIX_KEYPAD_ROWS_USE_OPEN_DRAIN 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPIO mode used for the row GPIOs
|
||||
*/
|
||||
#if CONFIG_MATRIX_KEYPAD_ROWS_USE_OPEN_DRAIN
|
||||
#define MATRIX_KEYPAD_ROWS_GPIO_MODE GPIO_OD_PU
|
||||
#else
|
||||
#define MATRIX_KEYPAD_ROWS_GPIO_MODE GPIO_OUT
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debounce pattern mask
|
||||
*/
|
||||
#define MATRIX_KEYPAD_DEBOUNCE_MASK \
|
||||
(CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_BEGIN | CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_END)
|
||||
|
||||
/**
|
||||
* @brief Type definition for a full row (all columns) state, variable width
|
||||
* depending on the number of columns.
|
||||
*/
|
||||
#if CONFIG_MATRIX_KEYPAD_NUM_COLUMNS <= 8
|
||||
typedef uint8_t matrix_keypad_state_row_t;
|
||||
#elif CONFIG_MATRIX_KEYPAD_NUM_COLUMNS <= 16
|
||||
typedef uint16_t matrix_keypad_state_row_t;
|
||||
#elif CONFIG_MATRIX_KEYPAD_NUM_COLUMNS <= 32
|
||||
typedef uint32_t matrix_keypad_state_row_t;
|
||||
#elif CONFIG_MATRIX_KEYPAD_NUM_COLUMNS <= 64
|
||||
typedef uint64_t matrix_keypad_state_row_t;
|
||||
#else
|
||||
#error Too many columns on matrix keypad.
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Device initialization parameters
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief GPIO pin array for the rows. GPIO_UNDEF is allowed and scanning
|
||||
* is skipped for these.
|
||||
*/
|
||||
gpio_t rows[CONFIG_MATRIX_KEYPAD_NUM_ROWS];
|
||||
/**
|
||||
* @brief GPIO pin array for the columns. GPIO_UNDEF is allowed and scanning
|
||||
* is skipped for these.
|
||||
*/
|
||||
gpio_t columns[CONFIG_MATRIX_KEYPAD_NUM_COLUMNS];
|
||||
/**
|
||||
* @brief Delay in microseconds between configuring the row gpio and reading
|
||||
* out the column. Can be zero to skip the delay.
|
||||
*/
|
||||
uint32_t row2col_delay;
|
||||
} matrix_keypad_params_t;
|
||||
|
||||
/**
|
||||
* @brief Callback for key state changes
|
||||
*
|
||||
* @param arg callback context
|
||||
* @param row Row that changed
|
||||
* @param column Column that changed
|
||||
* @param state New state of the key, 1 = pressed, 0 = released
|
||||
*/
|
||||
typedef void (*matrix_keypad_cb_t)(void *arg, size_t row, size_t column, bool state);
|
||||
|
||||
/**
|
||||
* @brief Device descriptor for the driver
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Device initialization parameters
|
||||
*/
|
||||
const matrix_keypad_params_t *params;
|
||||
|
||||
/**
|
||||
* @brief Debounce history
|
||||
*/
|
||||
uint8_t debounce[CONFIG_MATRIX_KEYPAD_NUM_ROWS][CONFIG_MATRIX_KEYPAD_NUM_COLUMNS];
|
||||
|
||||
/**
|
||||
* @brief Current button state
|
||||
*/
|
||||
matrix_keypad_state_row_t state[CONFIG_MATRIX_KEYPAD_NUM_ROWS];
|
||||
|
||||
/**
|
||||
* @brief callback context
|
||||
*/
|
||||
void *arg;
|
||||
|
||||
/**
|
||||
* @brief Callback called when a key changes state
|
||||
*/
|
||||
matrix_keypad_cb_t callback;
|
||||
} matrix_keypad_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the given device
|
||||
*
|
||||
* @param[inout] dev Device descriptor of the driver
|
||||
* @param[in] params Initialization parameters
|
||||
* @param[in] callback Callback to call on state changes
|
||||
* @param[in] arg Context argument for the callback
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int matrix_keypad_init(matrix_keypad_t *dev,
|
||||
const matrix_keypad_params_t *params,
|
||||
matrix_keypad_cb_t callback,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* @brief Scan through the keypad matrix
|
||||
*
|
||||
* This updates the state of the device descriptor, calling
|
||||
* @ref matrix_keypad_cb_t when a key press or release has been detected
|
||||
*
|
||||
* @param[inout] dev Device descriptor of the driver
|
||||
*
|
||||
* @return Number of keys that changed state
|
||||
*/
|
||||
size_t matrix_keypad_scan(matrix_keypad_t *dev);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MATRIX_KEYPAD_H */
|
||||
/** @} */
|
47
drivers/matrix_keypad/Kconfig
Normal file
47
drivers/matrix_keypad/Kconfig
Normal file
@ -0,0 +1,47 @@
|
||||
# Copyright (c) 2021 Koen Zandberg
|
||||
#
|
||||
# This file is subject to the terms and conditions of the GNU Lesser
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
|
||||
menuconfig MODULE_MATRIX_KEYPAD
|
||||
bool "Matrix Keypad"
|
||||
depends on TEST_KCONFIG
|
||||
depends on HAS_PERIPH_GPIO
|
||||
select MODULE_PERIPH_GPIO
|
||||
|
||||
if MODULE_MATRIX_KEYPAD
|
||||
|
||||
config MATRIX_KEYPAD_NUM_ROWS
|
||||
int "Number of rows on the matrix keypad"
|
||||
default 2
|
||||
|
||||
config MATRIX_KEYPAD_NUM_COLUMS
|
||||
int "Number of columns on the matrix keypad"
|
||||
default 2
|
||||
|
||||
config MATRIX_KEYPAD_DEBOUNCE_PATTERN_BEGIN
|
||||
hex "Bitmask pattern used for initial state of the switch"
|
||||
default 0xC0
|
||||
range 0x00 0xFF
|
||||
|
||||
config MATRIX_KEYPAD_DEBOUNCE_PATTERN_END
|
||||
hex "Bitmask pattern used for next state of the switch"
|
||||
default 0x07
|
||||
range 0x00 0xFF
|
||||
|
||||
config MATRIX_KEYPAD_ROWS_USE_OPEN_DRAIN
|
||||
bool "Use open drain output mode for the row GPIOs"
|
||||
default n
|
||||
help
|
||||
This switches the row GPIO mode from plain output mode to output mode
|
||||
with open drain. This helps to prevent shorts between GPIO pins when
|
||||
using matrix keypad modules without diodes in the switches. When diodes
|
||||
are installed with the switches this can safely be set off.
|
||||
|
||||
endif # MODULE_MATRIX_KEYPAD
|
||||
|
||||
config HAVE_MATRIX_KEYPAD
|
||||
bool
|
||||
help
|
||||
Indicates that a matrix-style keypad is present.
|
1
drivers/matrix_keypad/Makefile
Normal file
1
drivers/matrix_keypad/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
2
drivers/matrix_keypad/Makefile.dep
Normal file
2
drivers/matrix_keypad/Makefile.dep
Normal file
@ -0,0 +1,2 @@
|
||||
FEATURES_REQUIRED += periph_gpio
|
||||
USEMODULE += ztimer_usec
|
2
drivers/matrix_keypad/Makefile.include
Normal file
2
drivers/matrix_keypad/Makefile.include
Normal file
@ -0,0 +1,2 @@
|
||||
USEMODULE_INCLUDES_matrix_keypad := $(LAST_MAKEFILEDIR)/include
|
||||
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_matrix_keypad)
|
80
drivers/matrix_keypad/include/matrix_keypad_params.h
Normal file
80
drivers/matrix_keypad/include/matrix_keypad_params.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Koen Zandberg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_matrix_keypad
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
* @brief Default configuration
|
||||
*
|
||||
* @author Koen Zandberg <koen@bergzand.net>
|
||||
*/
|
||||
|
||||
#ifndef MATRIX_KEYPAD_PARAMS_H
|
||||
#define MATRIX_KEYPAD_PARAMS_H
|
||||
|
||||
#include "board.h"
|
||||
#include "matrix_keypad.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Set default configuration parameters
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Number of configured rows
|
||||
*/
|
||||
#ifndef MATRIX_KEYPAD_PARAM_ROWS
|
||||
#define MATRIX_KEYPAD_PARAM_ROWS { GPIO_PIN(0, 0), GPIO_PIN(0, 1) }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Number of configured columns
|
||||
*/
|
||||
#ifndef MATRIX_KEYPAD_PARAM_COLUMNS
|
||||
#define MATRIX_KEYPAD_PARAM_COLUMNS { GPIO_PIN(0, 2), GPIO_PIN(0, 3) }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Delay between switching the row state and reading the columns.
|
||||
*/
|
||||
#ifndef MATRIX_KEYPAD_PARAM_ROW2COL_DELAY
|
||||
#define MATRIX_KEYPAD_PARAM_ROW2COL_DELAY 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default param configuration
|
||||
*/
|
||||
#ifndef MATRIX_KEYPAD_PARAMS
|
||||
#define MATRIX_KEYPAD_PARAMS { \
|
||||
.rows = MATRIX_KEYPAD_PARAM_ROWS, \
|
||||
.columns = MATRIX_KEYPAD_PARAM_COLUMNS, \
|
||||
.row2col_delay = MATRIX_KEYPAD_PARAM_ROW2COL_DELAY, \
|
||||
}
|
||||
#endif
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* @brief Configuration struct
|
||||
*/
|
||||
static const matrix_keypad_params_t matrix_keypad_params[] =
|
||||
{
|
||||
MATRIX_KEYPAD_PARAMS
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MATRIX_KEYPAD_PARAMS_H */
|
||||
/** @} */
|
135
drivers/matrix_keypad/matrix_keypad.c
Normal file
135
drivers/matrix_keypad/matrix_keypad.c
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Koen Zandberg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_matrix_keypad
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Device driver implementation for the drivers
|
||||
*
|
||||
* @author Koen Zandberg <koen@bergzand.net>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "matrix_keypad.h"
|
||||
#include "matrix_keypad_params.h"
|
||||
|
||||
#include "periph/gpio.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
static uint8_t _mask_bits(uint8_t bits)
|
||||
{
|
||||
return bits & MATRIX_KEYPAD_DEBOUNCE_MASK;
|
||||
}
|
||||
|
||||
static void _flip_state(matrix_keypad_t *dev, size_t row, size_t column)
|
||||
{
|
||||
dev->state[row] ^= (1 << column);
|
||||
}
|
||||
|
||||
static void _setup_columns(matrix_keypad_t *dev)
|
||||
{
|
||||
for (size_t i = 0; i < CONFIG_MATRIX_KEYPAD_NUM_COLUMNS; i++) {
|
||||
gpio_t column = dev->params->columns[i];
|
||||
if (column != GPIO_UNDEF) {
|
||||
gpio_init(column, GPIO_IN_PU);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _setup_rows(matrix_keypad_t *dev)
|
||||
{
|
||||
for (size_t i = 0; i < CONFIG_MATRIX_KEYPAD_NUM_ROWS; i++) {
|
||||
gpio_t row = dev->params->rows[i];
|
||||
if (row != GPIO_UNDEF) {
|
||||
gpio_init(row, MATRIX_KEYPAD_ROWS_GPIO_MODE); /* Open drain to ensure rows don't conflict */
|
||||
gpio_set(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned _update_key(matrix_keypad_t *dev,
|
||||
size_t row, size_t column, bool status)
|
||||
{
|
||||
/* Pattern based debounce:
|
||||
* https://hackaday.com/2015/12/10/embed-with-elliot-debounce-your-noisy-buttons-part-ii/
|
||||
*/
|
||||
/* get the current stored state */
|
||||
bool state = dev->state[row] & (1 << column);
|
||||
/* get the history of the pin */
|
||||
uint8_t *debounce = &dev->debounce[row][column];
|
||||
|
||||
*debounce = (*debounce << 1) | status; /* Update state */
|
||||
|
||||
/* Pin history masking must match the begin pattern if it is currently
|
||||
* pressed and match the end pattern if it is released */
|
||||
uint8_t pattern = state ? CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_BEGIN
|
||||
: CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_END;
|
||||
|
||||
if (_mask_bits(*debounce) == pattern) {
|
||||
/* Changed */
|
||||
*debounce = 0U - (unsigned)state; /* 0x0 if released, 0xFF if pressed */
|
||||
_flip_state(dev, row, column);
|
||||
dev->callback(dev->arg, row, column, status);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int matrix_keypad_init(matrix_keypad_t *dev, const matrix_keypad_params_t *params,
|
||||
matrix_keypad_cb_t callback, void *arg)
|
||||
{
|
||||
static_assert(
|
||||
(CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_BEGIN & CONFIG_MATRIX_KEYPAD_DEBOUNCE_PATTERN_END) == 0,
|
||||
"Debounce patterns must not overlap");
|
||||
memset(dev, 0, sizeof(matrix_keypad_t));
|
||||
memcpy(&dev->params, params, sizeof(matrix_keypad_params_t));
|
||||
dev->callback = callback;
|
||||
dev->arg = arg;
|
||||
_setup_columns(dev);
|
||||
_setup_rows(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t matrix_keypad_scan(matrix_keypad_t *dev)
|
||||
{
|
||||
size_t res = 0;
|
||||
|
||||
/* Scan rows */
|
||||
for (size_t i = 0; i < CONFIG_MATRIX_KEYPAD_NUM_ROWS; i++) {
|
||||
gpio_t row = dev->params->rows[i];
|
||||
|
||||
if (row == GPIO_UNDEF) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Pull the row low */
|
||||
gpio_clear(row);
|
||||
|
||||
/* Wait for the row delay */
|
||||
if (dev->params->row2col_delay) {
|
||||
ztimer_sleep(ZTIMER_USEC, dev->params->row2col_delay);
|
||||
}
|
||||
|
||||
/* Scan columns */
|
||||
for (size_t j = 0; j < CONFIG_MATRIX_KEYPAD_NUM_COLUMNS; j++) {
|
||||
gpio_t column = dev->params->columns[j];
|
||||
if (column == GPIO_UNDEF) {
|
||||
continue;
|
||||
}
|
||||
bool status = !gpio_read(column);
|
||||
res += _update_key(dev, i, j, status);
|
||||
}
|
||||
/* Return the row to high-Z */
|
||||
gpio_set(row);
|
||||
}
|
||||
return res;
|
||||
}
|
7
tests/driver_matrix_keypad/Makefile
Normal file
7
tests/driver_matrix_keypad/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
# required modules
|
||||
USEMODULE += matrix_keypad
|
||||
USEMODULE += ztimer_msec
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
10
tests/driver_matrix_keypad/README.md
Normal file
10
tests/driver_matrix_keypad/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
matrix_keypad
|
||||
=============
|
||||
|
||||
This is a test application for the matrix_keypad module.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
The test application will print the key row and column when it is pressed or
|
||||
released.
|
53
tests/driver_matrix_keypad/main.c
Normal file
53
tests/driver_matrix_keypad/main.c
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Koen Zandberg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Test application for the matrix_keypad driver
|
||||
*
|
||||
* @author Koen Zandberg <koen@bergzand.net>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "matrix_keypad.h"
|
||||
#include "matrix_keypad_params.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
void _callback(void *arg, size_t col, size_t row, bool state)
|
||||
{
|
||||
(void)arg;
|
||||
printf("Key switch at column %u and row %u is ", (unsigned)col, (unsigned)row);
|
||||
if (state) {
|
||||
puts("pressed!");
|
||||
}
|
||||
else {
|
||||
puts("released!");
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
matrix_keypad_t dev;
|
||||
|
||||
puts("Generated RIOT application: 'matrix_keypad'");
|
||||
if (matrix_keypad_init(&dev, &matrix_keypad_params[0], _callback, NULL) == 0) {
|
||||
puts("[OK]\n");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
matrix_keypad_scan(&dev);
|
||||
ztimer_sleep(ZTIMER_MSEC, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user