diff --git a/examples/peripherals/gpio/CMakeLists.txt b/examples/peripherals/gpio/generic_gpio/CMakeLists.txt similarity index 90% rename from examples/peripherals/gpio/CMakeLists.txt rename to examples/peripherals/gpio/generic_gpio/CMakeLists.txt index 6ac490d38a..fe757473aa 100644 --- a/examples/peripherals/gpio/CMakeLists.txt +++ b/examples/peripherals/gpio/generic_gpio/CMakeLists.txt @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(gpio) +project(generic-gpio) diff --git a/examples/peripherals/gpio/Makefile b/examples/peripherals/gpio/generic_gpio/Makefile similarity index 84% rename from examples/peripherals/gpio/Makefile rename to examples/peripherals/gpio/generic_gpio/Makefile index 0589a9f21d..9422164da3 100644 --- a/examples/peripherals/gpio/Makefile +++ b/examples/peripherals/gpio/generic_gpio/Makefile @@ -3,7 +3,7 @@ # project subdirectory. # -PROJECT_NAME := gpio +PROJECT_NAME := generic-gpio include $(IDF_PATH)/make/project.mk diff --git a/examples/peripherals/gpio/README.md b/examples/peripherals/gpio/generic_gpio/README.md similarity index 100% rename from examples/peripherals/gpio/README.md rename to examples/peripherals/gpio/generic_gpio/README.md diff --git a/examples/peripherals/gpio/example_test.py b/examples/peripherals/gpio/generic_gpio/example_test.py similarity index 89% rename from examples/peripherals/gpio/example_test.py rename to examples/peripherals/gpio/generic_gpio/example_test.py index 935bef36cd..a0564846b4 100644 --- a/examples/peripherals/gpio/example_test.py +++ b/examples/peripherals/gpio/generic_gpio/example_test.py @@ -10,7 +10,7 @@ import ttfw_idf @ttfw_idf.idf_example_test(env_tag="Example_TWAI1", target=['esp32', 'esp32s2'], ci_target=['esp32']) def test_examples_gpio(env, extra_data): app_name = "gpio" - dut = env.get_dut(app_name, "examples/peripherals/gpio") + dut = env.get_dut(app_name, "examples/peripherals/gpio/generic_gpio") dut.start_app() res = dut.expect(ttfw_idf.MINIMUM_FREE_HEAP_SIZE_RE) if not res: diff --git a/examples/peripherals/gpio/main/CMakeLists.txt b/examples/peripherals/gpio/generic_gpio/main/CMakeLists.txt similarity index 100% rename from examples/peripherals/gpio/main/CMakeLists.txt rename to examples/peripherals/gpio/generic_gpio/main/CMakeLists.txt diff --git a/examples/peripherals/gpio/main/component.mk b/examples/peripherals/gpio/generic_gpio/main/component.mk similarity index 100% rename from examples/peripherals/gpio/main/component.mk rename to examples/peripherals/gpio/generic_gpio/main/component.mk diff --git a/examples/peripherals/gpio/main/gpio_example_main.c b/examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c similarity index 100% rename from examples/peripherals/gpio/main/gpio_example_main.c rename to examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c diff --git a/examples/peripherals/gpio/matrix_keyboard/CMakeLists.txt b/examples/peripherals/gpio/matrix_keyboard/CMakeLists.txt new file mode 100644 index 0000000000..fddd4236e9 --- /dev/null +++ b/examples/peripherals/gpio/matrix_keyboard/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(matrix-keyboard) \ No newline at end of file diff --git a/examples/peripherals/gpio/matrix_keyboard/README.md b/examples/peripherals/gpio/matrix_keyboard/README.md new file mode 100644 index 0000000000..31cd207e55 --- /dev/null +++ b/examples/peripherals/gpio/matrix_keyboard/README.md @@ -0,0 +1,79 @@ +| Supported Targets | ESP32-S2 | +| ----------------- | -------- | + +# Matrix Keyboard Example (based on Dedicated GPIO) + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +## Overview + +This example mainly illustrates how to drive a common matrix keyboard using the dedicated GPIO APIs, including: + +* Manipulate the level on a group of GPIOs +* Trigger edge interrupt +* Read level on a group of GPIOs + +Dedicated GPIO is designed to speed up CPU operations on one or a group of GPIOs by writing assembly codes with Espressif customized instructions (please refer TRM to get more information about these instructions). + +This matrix keyboard driver is interrupt-driven, supports a configurable debounce time. GPIOs used by row and column lines are also configurable during driver installation stage. + +## How to use example + +### Hardware Required + +This example can run on any target that has the dedicated feature (e.g. ESP32-S2). It's not necessary for your matrix board to have pull-up resisters on row/column lines. The driver has enabled internal pull-up resister by default. A typical matrix board should look as follows: + +``` +row_0 +--------+-------------------+------------------------------+-----------------+ + | | | + | + | + | + + | +-+-+ | +-+-+ ...... | +-+-+ + . +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ + . | | | + . . | . | . | + . | . | ...... . | + . | . | . | + . | . | . | + | | | +row_n +--------+-------------------+------------------------------+-----------------+ + | | | | | | + | + | | + | | + | + | +-+-+ | | +-+-+ | ...... | +-+-+ | + +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ + | | | + | | | + | | | + + + + + col_0 col_1 ...... col_m +``` + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +(Replace PORT with the name of the serial port to use.) + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +``` +I (2883) example: press event, key code = 0002 +I (3003) example: release event, key code = 0002 +I (5053) example: press event, key code = 0001 +I (5203) example: release event, key code = 0001 +I (6413) example: press event, key code = 0000 +I (6583) example: release event, key code = 0000 +I (7963) example: press event, key code = 0003 +I (8113) example: release event, key code = 0003 +I (8773) example: press event, key code = 0103 +I (8923) example: release event, key code = 0103 +I (9543) example: press event, key code = 0203 +I (9683) example: release event, key code = 0203 +``` diff --git a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/CMakeLists.txt b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/CMakeLists.txt new file mode 100644 index 0000000000..167e6b2d80 --- /dev/null +++ b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/CMakeLists.txt @@ -0,0 +1,7 @@ +set(component_srcs "src/matrix_keyboard.c") + +idf_component_register(SRCS "${component_srcs}" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "" + PRIV_REQUIRES "driver" + REQUIRES "") diff --git a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h new file mode 100644 index 0000000000..825ae31469 --- /dev/null +++ b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h @@ -0,0 +1,142 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAKE_KEY_CODE(row, col) ((row << 8) | (col)) +#define GET_KEY_CODE_ROW(code) ((code >> 8) & 0xFF) +#define GET_KEY_CODE_COL(code) (code & 0xFF) + +/** + * @brief Type defined for matrix keyboard handle + * + */ +typedef struct matrix_kbd_t *matrix_kbd_handle_t; + +/** + * @brief Matrix keyboard event ID + * + */ +typedef enum { + MATRIX_KBD_EVENT_DOWN, /*!< Key is pressed down */ + MATRIX_KBD_EVENT_UP /*!< Key is released */ +} matrix_kbd_event_id_t; + +/** + * @brief Type defined for matrix keyboard event handler + * + * @note The event handler runs in a OS timer context + * + * @param[in] mkbd_handle Handle of matrix keyboard that return from `matrix_kbd_install` + * @param[in] event Event ID, refer to `matrix_kbd_event_id_t` to see all supported events + * @param[in] event_data Data for corresponding event + * @param[in] handler_args Arguments that user passed in from `matrix_kbd_register_event_handler` + * @return Currently always return ESP_OK + */ +typedef esp_err_t (*matrix_kbd_event_handler)(matrix_kbd_handle_t mkbd_handle, matrix_kbd_event_id_t event, void *event_data, void *handler_args); + +/** + * @brief Configuration structure defined for matrix keyboard + * + */ +typedef struct { + const int *row_gpios; /*!< Array, contains GPIO numbers used by row line */ + const int *col_gpios; /*!< Array, contains GPIO numbers used by column line */ + uint32_t nr_row_gpios; /*!< row_gpios array size */ + uint32_t nr_col_gpios; /*!< col_gpios array size */ + uint32_t debounce_ms; /*!< Debounce time */ +} matrix_kbd_config_t; + +/** + * @brief Default configuration for matrix keyboard driver + * + */ +#define MATRIX_KEYBOARD_DEFAULT_CONFIG() \ +{ \ + .row_gpios = NULL, \ + .col_gpios = NULL, \ + .nr_row_gpios = 0, \ + .nr_col_gpios = 0, \ + .debounce_ms = 20, \ +} + +/** + * @brief Install matrix keyboard driver + * + * @param[in] config Configuration of matrix keyboard driver + * @param[out] mkbd_handle Returned matrix keyboard handle if installation succeed + * @return + * - ESP_OK: Install matrix keyboard driver successfully + * - ESP_ERR_INVALID_ARG: Install matrix keyboard driver failed because of some invalid argument + * - ESP_ERR_NO_MEM: Install matrix keyboard driver failed because there's no enough capable memory + * - ESP_FAIL: Install matrix keyboard driver failed because of other error + */ +esp_err_t matrix_kbd_install(const matrix_kbd_config_t *config, matrix_kbd_handle_t *mkbd_handle); + +/** + * @brief Uninstall matrix keyboard driver + * + * @param[in] mkbd_handle Handle of matrix keyboard that return from `matrix_kbd_install` + * @return + * - ESP_OK: Uninstall matrix keyboard driver successfully + * - ESP_ERR_INVALID_ARG: Uninstall matrix keyboard driver failed because of some invalid argument + * - ESP_FAIL: Uninstall matrix keyboard driver failed because of other error + */ +esp_err_t matrix_kbd_uninstall(matrix_kbd_handle_t mkbd_handle); + +/** + * @brief Start matrix keyboard driver + * + * @param[in] mkbd_handle Handle of matrix keyboard that return from `matrix_kbd_install` + * @return + * - ESP_OK: Start matrix keyboard driver successfully + * - ESP_ERR_INVALID_ARG: Start matrix keyboard driver failed because of some invalid argument + * - ESP_FAIL: Start matrix keyboard driver failed because of other error + */ +esp_err_t matrix_kbd_start(matrix_kbd_handle_t mkbd_handle); + +/** + * @brief Stop matrix kayboard driver + * + * @param[in] mkbd_handle Handle of matrix keyboard that return from `matrix_kbd_install` + * @return + * - ESP_OK: Stop matrix keyboard driver successfully + * - ESP_ERR_INVALID_ARG: Stop matrix keyboard driver failed because of some invalid argument + * - ESP_FAIL: Stop matrix keyboard driver failed because of other error + */ +esp_err_t matrix_kbd_stop(matrix_kbd_handle_t mkbd_handle); + +/** + * @brief Register matrix keyboard event handler + * + * @param[in] mkbd_handle Handle of matrix keyboard that return from `matrix_kbd_install` + * @param[in] handler Event handler + * @param[in] args Arguments that will be passed to the handler + * @return + * - ESP_OK: Register event handler successfully + * - ESP_ERR_INVALID_ARG: Register event handler failed because of some invalid argument + * - ESP_FAIL: Register event handler failed because of other error + */ +esp_err_t matrix_kbd_register_event_handler(matrix_kbd_handle_t mkbd_handle, matrix_kbd_event_handler handler, void *args); + +#ifdef __cplusplus +} +#endif diff --git a/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c new file mode 100644 index 0000000000..e801b02846 --- /dev/null +++ b/examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/src/matrix_keyboard.c @@ -0,0 +1,245 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/timers.h" +#include "esp_compiler.h" +#include "esp_log.h" +#include "driver/dedic_gpio.h" +#include "driver/gpio.h" +#include "matrix_keyboard.h" +#include "esp_rom_sys.h" + +static const char *TAG = "mkbd"; + +#define MKBD_CHECK(a, msg, tag, ret, ...) \ + do { \ + if (unlikely(!(a))) { \ + ESP_LOGE(TAG, "%s(%d): " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ret_code = ret; \ + goto tag; \ + } \ + } while (0) + +typedef struct matrix_kbd_t matrix_kbd_t; + +struct matrix_kbd_t { + dedic_gpio_bundle_handle_t row_bundle; + dedic_gpio_bundle_handle_t col_bundle; + uint32_t nr_row_gpios; + uint32_t nr_col_gpios; + TimerHandle_t debounce_timer; + matrix_kbd_event_handler event_handler; + void *event_handler_args; + uint32_t row_state[0]; +}; + +static IRAM_ATTR bool matrix_kbd_row_isr_callback(dedic_gpio_bundle_handle_t row_bundle, uint32_t row_index, void *args) +{ + BaseType_t high_task_wakeup = pdFALSE; + matrix_kbd_t *mkbd = (matrix_kbd_t *)args; + + // temporarily disable interrupt + dedic_gpio_bundle_set_interrupt_and_callback(row_bundle, (1 << mkbd->nr_row_gpios) - 1, DEDIC_GPIO_INTR_NONE, NULL, NULL); + // get row id, start to check the col id + dedic_gpio_bundle_write(row_bundle, 1 << row_index, 0); + dedic_gpio_bundle_write(mkbd->col_bundle, (1 << mkbd->nr_col_gpios) - 1, (1 << mkbd->nr_col_gpios) - 1); + xTimerStartFromISR(mkbd->debounce_timer, &high_task_wakeup); + return high_task_wakeup == pdTRUE; +} + +static void matrix_kbd_debounce_timer_callback(TimerHandle_t xTimer) +{ + matrix_kbd_t *mkbd = (matrix_kbd_t *)pvTimerGetTimerID(xTimer); + + uint32_t row_out = dedic_gpio_bundle_read_out(mkbd->row_bundle); + uint32_t col_in = dedic_gpio_bundle_read_in(mkbd->col_bundle); + row_out = (~row_out) & ((1 << mkbd->nr_row_gpios) - 1); + ESP_LOGD(TAG, "row_out=%x, col_in=%x", row_out, col_in); + int row = -1; + int col = -1; + uint32_t key_code = 0; + while (row_out) { + row = __builtin_ffs(row_out) - 1; + uint32_t changed_col_bits = mkbd->row_state[row] ^ col_in; + while (changed_col_bits) { + col = __builtin_ffs(changed_col_bits) - 1; + ESP_LOGD(TAG, "row=%d, col=%d", row, col); + key_code = MAKE_KEY_CODE(row, col); + if (col_in & (1 << col)) { + mkbd->event_handler(mkbd, MATRIX_KBD_EVENT_UP, (void *)key_code, mkbd->event_handler_args); + } else { + mkbd->event_handler(mkbd, MATRIX_KBD_EVENT_DOWN, (void *)key_code, mkbd->event_handler_args); + } + changed_col_bits = changed_col_bits & (changed_col_bits - 1); + } + mkbd->row_state[row] = col_in; + row_out = row_out & (row_out - 1); + } + + // row lines set to high level + dedic_gpio_bundle_write(mkbd->row_bundle, (1 << mkbd->nr_row_gpios) - 1, (1 << mkbd->nr_row_gpios) - 1); + // col lines set to low level + dedic_gpio_bundle_write(mkbd->col_bundle, (1 << mkbd->nr_col_gpios) - 1, 0); + dedic_gpio_bundle_set_interrupt_and_callback(mkbd->row_bundle, (1 << mkbd->nr_row_gpios) - 1, + DEDIC_GPIO_INTR_BOTH_EDGE, matrix_kbd_row_isr_callback, mkbd); +} + +esp_err_t matrix_kbd_install(const matrix_kbd_config_t *config, matrix_kbd_handle_t *mkbd_handle) +{ + esp_err_t ret_code = ESP_OK; + matrix_kbd_t *mkbd = NULL; + MKBD_CHECK(config, "matrix keyboard configuration can't be null", err, ESP_ERR_INVALID_ARG); + MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + + mkbd = calloc(1, sizeof(matrix_kbd_t) + (config->nr_row_gpios) * sizeof(uint32_t)); + MKBD_CHECK(mkbd, "allocate matrix keyboard context failed", err, ESP_ERR_NO_MEM); + + mkbd->nr_col_gpios = config->nr_col_gpios; + mkbd->nr_row_gpios = config->nr_row_gpios; + + // GPIO pad configuration + // Each GPIO used in matrix key board should be able to input and output + // In case the keyboard doesn't design a resister to pull up row/col line + // We enable the internal pull up resister, enable Open Drain as well + gpio_config_t io_conf = { + .mode = GPIO_MODE_INPUT_OUTPUT_OD, + .pull_up_en = 1 + }; + + for (int i = 0; i < config->nr_row_gpios; i++) { + io_conf.pin_bit_mask = 1ULL << config->row_gpios[i]; + gpio_config(&io_conf); + } + + dedic_gpio_bundle_config_t bundle_row_config = { + .gpio_array = config->row_gpios, + .array_size = config->nr_row_gpios, + .flags = { + .in_en = 1, + .out_en = 1, + }, + }; + MKBD_CHECK(dedic_gpio_new_bundle(&bundle_row_config, &mkbd->row_bundle) == ESP_OK, + "create row bundle failed", err, ESP_FAIL); + + for (int i = 0; i < config->nr_col_gpios; i++) { + io_conf.pin_bit_mask = 1ULL << config->col_gpios[i]; + gpio_config(&io_conf); + } + + dedic_gpio_bundle_config_t bundle_col_config = { + .gpio_array = config->col_gpios, + .array_size = config->nr_col_gpios, + .flags = { + .in_en = 1, + .out_en = 1, + }, + }; + MKBD_CHECK(dedic_gpio_new_bundle(&bundle_col_config, &mkbd->col_bundle) == ESP_OK, + "create col bundle failed", err, ESP_FAIL); + + // Disable interrupt + dedic_gpio_bundle_set_interrupt_and_callback(mkbd->row_bundle, (1 << config->nr_row_gpios) - 1, + DEDIC_GPIO_INTR_NONE, NULL, NULL); + dedic_gpio_bundle_set_interrupt_and_callback(mkbd->col_bundle, (1 << config->nr_col_gpios) - 1, + DEDIC_GPIO_INTR_NONE, NULL, NULL); + + // Create a ont-shot os timer, used for key debounce + mkbd->debounce_timer = xTimerCreate("kb_debounce", pdMS_TO_TICKS(config->debounce_ms), pdFALSE, mkbd, matrix_kbd_debounce_timer_callback); + MKBD_CHECK(mkbd->debounce_timer, "create debounce timer failed", err, ESP_FAIL); + + * mkbd_handle = mkbd; + return ESP_OK; +err: + if (mkbd) { + if (mkbd->debounce_timer) { + xTimerDelete(mkbd->debounce_timer, 0); + } + if (mkbd->col_bundle) { + dedic_gpio_del_bundle(mkbd->col_bundle); + } + if (mkbd->row_bundle) { + dedic_gpio_del_bundle(mkbd->row_bundle); + } + free(mkbd); + } + return ret_code; +} + +esp_err_t matrix_kbd_uninstall(matrix_kbd_handle_t mkbd_handle) +{ + esp_err_t ret_code = ESP_OK; + MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + xTimerDelete(mkbd_handle->debounce_timer, 0); + dedic_gpio_del_bundle(mkbd_handle->col_bundle); + dedic_gpio_del_bundle(mkbd_handle->row_bundle); + free(mkbd_handle); + return ESP_OK; +err: + return ret_code; +} + +esp_err_t matrix_kbd_start(matrix_kbd_handle_t mkbd_handle) +{ + esp_err_t ret_code = ESP_OK; + MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + + // row lines set to high level + dedic_gpio_bundle_write(mkbd_handle->row_bundle, (1 << mkbd_handle->nr_row_gpios) - 1, (1 << mkbd_handle->nr_row_gpios) - 1); + // col lines set to low level + dedic_gpio_bundle_write(mkbd_handle->col_bundle, (1 << mkbd_handle->nr_col_gpios) - 1, 0); + + for (int i = 0; i < mkbd_handle->nr_row_gpios; i++) { + mkbd_handle->row_state[i] = (1 << mkbd_handle->nr_col_gpios) - 1; + } + + // only enable row line interrupt + dedic_gpio_bundle_set_interrupt_and_callback(mkbd_handle->row_bundle, (1 << mkbd_handle->nr_row_gpios) - 1, + DEDIC_GPIO_INTR_BOTH_EDGE, matrix_kbd_row_isr_callback, mkbd_handle); + + return ESP_OK; +err: + return ret_code; +} + +esp_err_t matrix_kbd_stop(matrix_kbd_handle_t mkbd_handle) +{ + esp_err_t ret_code = ESP_OK; + MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + + xTimerStop(mkbd_handle->debounce_timer, 0); + + // Disable interrupt + dedic_gpio_bundle_set_interrupt_and_callback(mkbd_handle->row_bundle, (1 << mkbd_handle->nr_row_gpios) - 1, + DEDIC_GPIO_INTR_NONE, NULL, NULL); + dedic_gpio_bundle_set_interrupt_and_callback(mkbd_handle->col_bundle, (1 << mkbd_handle->nr_col_gpios) - 1, + DEDIC_GPIO_INTR_NONE, NULL, NULL); + + return ESP_OK; +err: + return ret_code; +} + +esp_err_t matrix_kbd_register_event_handler(matrix_kbd_handle_t mkbd_handle, matrix_kbd_event_handler handler, void *args) +{ + esp_err_t ret_code = ESP_OK; + MKBD_CHECK(mkbd_handle, "matrix keyboard handle can't be null", err, ESP_ERR_INVALID_ARG); + mkbd_handle->event_handler = handler; + mkbd_handle->event_handler_args = args; + return ESP_OK; +err: + return ret_code; +} diff --git a/examples/peripherals/gpio/matrix_keyboard/main/CMakeLists.txt b/examples/peripherals/gpio/matrix_keyboard/main/CMakeLists.txt new file mode 100644 index 0000000000..357c4dd2f2 --- /dev/null +++ b/examples/peripherals/gpio/matrix_keyboard/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "matrix_keyboard_example_main.c" + INCLUDE_DIRS "") \ No newline at end of file diff --git a/examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c b/examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c new file mode 100644 index 0000000000..af121e0815 --- /dev/null +++ b/examples/peripherals/gpio/matrix_keyboard/main/matrix_keyboard_example_main.c @@ -0,0 +1,53 @@ +/* Matrix Keyboard (based on dedicated GPIO) example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "esp_log.h" +#include "matrix_keyboard.h" + +const static char *TAG = "example"; + +/** + * @brief Matrix keyboard event handler + * @note This function is run under OS timer task context + */ +esp_err_t example_matrix_kbd_event_handler(matrix_kbd_handle_t mkbd_handle, matrix_kbd_event_id_t event, void *event_data, void *handler_args) +{ + uint32_t key_code = (uint32_t)event_data; + switch (event) { + case MATRIX_KBD_EVENT_DOWN: + ESP_LOGI(TAG, "press event, key code = %04x", key_code); + break; + case MATRIX_KBD_EVENT_UP: + ESP_LOGI(TAG, "release event, key code = %04x", key_code); + break; + } + return ESP_OK; +} + +void app_main(void) +{ + matrix_kbd_handle_t kbd = NULL; + // Apply default matrix keyboard configuration + matrix_kbd_config_t config = MATRIX_KEYBOARD_DEFAULT_CONFIG(); + // Set GPIOs used by row and column line + config.col_gpios = (int[]) { + 10, 11, 12, 13 + }; + config.nr_col_gpios = 4; + config.row_gpios = (int[]) { + 14, 15, 16, 17 + }; + config.nr_row_gpios = 4; + // Install matrix keyboard driver + matrix_kbd_install(&config, &kbd); + // Register keyboard input event handler + matrix_kbd_register_event_handler(kbd, example_matrix_kbd_event_handler, NULL); + // Keyboard start to work + matrix_kbd_start(kbd); +}