From 6227cd4fd4946c33da4a8f759aa2fda0a0c903d6 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz Date: Fri, 24 Mar 2023 14:26:06 -0300 Subject: [PATCH] boards/xtensa/esp32s2-kaluga-1: Add touch pad support --- arch/xtensa/src/esp32s2/esp32s2_touch.c | 4 + .../xtensa/esp32s2/esp32s2-kaluga-1/Kconfig | 48 +++ .../configs/buttons/defconfig | 53 +++ .../esp32s2/esp32s2-kaluga-1/include/board.h | 23 ++ .../esp32s2/esp32s2-kaluga-1/src/Make.defs | 4 + .../esp32s2-kaluga-1/src/esp32s2-kaluga-1.h | 12 +- .../esp32s2-kaluga-1/src/esp32s2_bringup.c | 10 + .../esp32s2-kaluga-1/src/esp32s2_buttons.c | 342 ++++++++++++++++++ 8 files changed, 493 insertions(+), 3 deletions(-) create mode 100644 boards/xtensa/esp32s2/esp32s2-kaluga-1/configs/buttons/defconfig create mode 100644 boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2_buttons.c diff --git a/arch/xtensa/src/esp32s2/esp32s2_touch.c b/arch/xtensa/src/esp32s2/esp32s2_touch.c index d2c0d74a75..51d764713f 100644 --- a/arch/xtensa/src/esp32s2/esp32s2_touch.c +++ b/arch/xtensa/src/esp32s2/esp32s2_touch.c @@ -531,7 +531,11 @@ bool esp32s2_touchread(enum touch_pad_e tp) leave_critical_section(flags); +#ifdef CONFIG_ESP32S2_TOUCH_THRESHOLD_POSEDGE + return (value < touch_pad_logic_threshold[tp]); +#else return (value > touch_pad_logic_threshold[tp]); +#endif } /**************************************************************************** diff --git a/boards/xtensa/esp32s2/esp32s2-kaluga-1/Kconfig b/boards/xtensa/esp32s2/esp32s2-kaluga-1/Kconfig index 6092e1e13f..2a686e7679 100644 --- a/boards/xtensa/esp32s2/esp32s2-kaluga-1/Kconfig +++ b/boards/xtensa/esp32s2/esp32s2-kaluga-1/Kconfig @@ -5,4 +5,52 @@ if ARCH_BOARD_ESP32S2_KALUGA_1 +config ESP32S2_TOUCH + bool "Touch pads" + default n + ---help--- + Enable ESP32-S2 touch pad support. + +if ESP32S2_TOUCH + +config ESP32S2_TOUCH_THRESHOLD_POSEDGE + bool "Touch pad inverted threshold detection" + default y + ---help--- + Detect positive edge of touch pad threshold rather than negative edge. + +config ESP32S2_TOUCH_FILTER + bool "Touch pad filter" + default n + ---help--- + Enable internal filter for the touch pads. + +config ESP32S2_TOUCH_DENOISE + bool "Touch pad denoise" + default n + ---help--- + Enable internal denoise for the touch pads. + +config ESP32S2_TOUCH_IRQ + bool "Enable touch pad interrupts" + select ESP32S2_RTCIO_IRQ + select ESP32S2_RT_TIMER + depends on ARCH_IRQBUTTONS + default n + ---help--- + Enable interrupt support for the touch pads. + +config ESP32S2_TOUCH_IRQ_INTERVAL_MS + int "Minimum interrupt interval (ms)" + depends on ESP32S2_TOUCH_IRQ + default 100 + ---help--- + Minimum interval between touch pad interrupts (in milliseconds). + As the RTC interrupts are triggered by level, this interrupt + will be constantly set off as long as the touch pad is pressed. + To avoid that, we disable the interrupt when it is triggered and + set a timer for it to be re-enabled. + +endif # ESP32S2_TOUCH + endif # ARCH_BOARD_ESP32S2_KALUGA_1 diff --git a/boards/xtensa/esp32s2/esp32s2-kaluga-1/configs/buttons/defconfig b/boards/xtensa/esp32s2/esp32s2-kaluga-1/configs/buttons/defconfig new file mode 100644 index 0000000000..046930d23c --- /dev/null +++ b/boards/xtensa/esp32s2/esp32s2-kaluga-1/configs/buttons/defconfig @@ -0,0 +1,53 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="esp32s2-kaluga-1" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32S2_KALUGA_1=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP="esp32s2" +CONFIG_ARCH_CHIP_ESP32S2=y +CONFIG_ARCH_CHIP_ESP32S2WROVER=y +CONFIG_ARCH_IRQBUTTONS=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_ESP32S2_GPIO_IRQ=y +CONFIG_ESP32S2_TOUCH=y +CONFIG_ESP32S2_TOUCH_IRQ=y +CONFIG_ESP32S2_UART0=y +CONFIG_EXAMPLES_BUTTONS=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INPUT=y +CONFIG_INPUT_BUTTONS=y +CONFIG_INPUT_BUTTONS_LOWER=y +CONFIG_INTELHEX_BINARY=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SPI=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/xtensa/esp32s2/esp32s2-kaluga-1/include/board.h b/boards/xtensa/esp32s2/esp32s2-kaluga-1/include/board.h index 6d8da0f892..529458a6b2 100644 --- a/boards/xtensa/esp32s2/esp32s2-kaluga-1/include/board.h +++ b/boards/xtensa/esp32s2/esp32s2-kaluga-1/include/board.h @@ -43,6 +43,29 @@ # define BOARD_CLOCK_FREQUENCY 80000000 #endif +/* Button definitions *******************************************************/ + +#define BUTTON_BTN1 0 /* BUTTON_BOOT */ +#define BUTTON_BTN1_BIT (1 << BUTTON_BTN1) + +#ifdef CONFIG_ESP32S2_TOUCH +# define BUTTON_BTN2 1 /* TOUCHPAD_PHOTO */ +# define BUTTON_BTN2_BIT (1 << BUTTON_BTN2) +# define BUTTON_BTN3 2 /* TOUCHPAD_PLAY */ +# define BUTTON_BTN3_BIT (1 << BUTTON_BTN3) +# define BUTTON_BTN4 3 /* TOUCHPAD_RECORD */ +# define BUTTON_BTN4_BIT (1 << BUTTON_BTN4) +# define BUTTON_BTN5 4 /* TOUCHPAD_NETWORK */ +# define BUTTON_BTN5_BIT (1 << BUTTON_BTN5) +# define BUTTON_BTN6 5 /* TOUCHPAD_VOLUP */ +# define BUTTON_BTN6_BIT (1 << BUTTON_BTN6) +# define BUTTON_BTN7 6 /* TOUCHPAD_VOLDN */ +# define BUTTON_BTN7_BIT (1 << BUTTON_BTN7) +# define NUM_BUTTONS 7 +#else +# define NUM_BUTTONS 1 +#endif + /* LED definitions **********************************************************/ /* Define how many LEDs this board has (needed by userleds) */ diff --git a/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/Make.defs b/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/Make.defs index 478ded534c..80762d69e5 100644 --- a/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/Make.defs +++ b/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/Make.defs @@ -45,6 +45,10 @@ ifeq ($(CONFIG_ESP32S2_SPI),y) CSRCS += esp32s2_board_spi.c endif +ifeq ($(CONFIG_ARCH_BUTTONS),y) +CSRCS += esp32s2_buttons.c +endif + DEPPATH += --dep-path board VPATH += :board CFLAGS += $(shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board) diff --git a/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2-kaluga-1.h b/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2-kaluga-1.h index 44ca03827f..1d51eec7c3 100644 --- a/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2-kaluga-1.h +++ b/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2-kaluga-1.h @@ -33,11 +33,17 @@ * Pre-processor Definitions ****************************************************************************/ -/* ESP32S2-DevKitC GPIOs ****************************************************/ +/* ESP32S2-Kaluga-1 GPIOs ***************************************************/ -/* BOOT Button */ +/* Buttons */ -#define BUTTON_BOOT 0 +#define BUTTON_BOOT 0 +#define TP_PHOTO_CHANNEL 6 +#define TP_PLAY_CHANNEL 2 +#define TP_RECORD_CHANNEL 5 +#define TP_NETWORK_CHANNEL 11 +#define TP_VOLUP_CHANNEL 1 +#define TP_VOLDN_CHANNEL 3 /* TIMERS */ diff --git a/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2_bringup.c b/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2_bringup.c index 6948159833..ff241e2fb2 100644 --- a/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2_bringup.c +++ b/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2_bringup.c @@ -206,6 +206,16 @@ int esp32s2_bringup(void) } #endif +#ifdef CONFIG_INPUT_BUTTONS + /* Register the BUTTON driver */ + + ret = btn_lower_initialize("/dev/buttons"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: btn_lower_initialize() failed: %d\n", ret); + } +#endif + /* If we got here then perhaps not all initialization was successful, but * at least enough succeeded to bring-up NSH with perhaps reduced * capabilities. diff --git a/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2_buttons.c b/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2_buttons.c new file mode 100644 index 0000000000..25160afe23 --- /dev/null +++ b/boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2_buttons.c @@ -0,0 +1,342 @@ +/**************************************************************************** + * boards/xtensa/esp32s2/esp32s2-kaluga-1/src/esp32s2_buttons.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "esp32s2_gpio.h" +#include "esp32s2_rtc_gpio.h" +#include "esp32s2_touch.h" + +#include "esp32s2-kaluga-1.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +#define TOUCHPAD_REFH (TOUCH_HVOLT_2V7) +#define TOUCHPAD_REFL (TOUCH_LVOLT_0V5) +#define TOUCHPAD_ATTEN (TOUCH_HVOLT_ATTEN_1V) +#define TOUCHPAD_SLOPE (TOUCH_SLOPE_7) +#define TOUCHPAD_TIE_OPT (TOUCH_TIE_OPT_LOW) +#define TOUCHPAD_FSM_MODE (TOUCH_FSM_MODE_TIMER) +#define TOUCHPAD_DENOISE_GRADE (TOUCH_DENOISE_BIT4) +#define TOUCHPAD_DENOISE_CAP (TOUCH_DENOISE_CAP_L4) +#define TOUCHPAD_FILTER_MODE (TOUCH_FILTER_IIR_16) +#define TOUCHPAD_FILTER_DEBOUNCE (1) +#define TOUCHPAD_FILTER_NOISE (0) +#define TOUCHPAD_FILTER_JITTER (4) +#define TOUCHPAD_FILTER_SMH (TOUCH_SMOOTH_IIR_2) +#define TOUCHPAD_THRESHOLD (30000) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct button_type_s +{ + bool is_touchpad; + union + { + int channel; + int gpio; + } input; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_ESP32S2_TOUCH +static const struct touch_config_s tp_config = +{ + .refh = TOUCHPAD_REFH, + .refl = TOUCHPAD_REFL, + .atten = TOUCHPAD_ATTEN, + .slope = TOUCHPAD_SLOPE, + .tie_opt = TOUCHPAD_TIE_OPT, + .fsm_mode = TOUCHPAD_FSM_MODE, +# ifdef CONFIG_ESP32S2_TOUCH_FILTER + .filter_mode = TOUCHPAD_FILTER_MODE, + .filter_debounce_cnt = TOUCHPAD_FILTER_DEBOUNCE, + .filter_noise_thr = TOUCHPAD_FILTER_NOISE, + .filter_jitter_step = TOUCHPAD_FILTER_JITTER, + .filter_smh_lvl = TOUCHPAD_FILTER_SMH, +# endif +# ifdef CONFIG_ESP32S2_TOUCH_DENOISE + .denoise_grade = TOUCHPAD_DENOISE_GRADE, + .denoise_cap_level = TOUCHPAD_DENOISE_CAP +# endif +}; +#endif + +static const struct button_type_s g_buttons[] = +{ + { + .is_touchpad = false, + .input.gpio = BUTTON_BOOT + }, +#ifdef CONFIG_ESP32S2_TOUCH + { + .is_touchpad = true, + .input.channel = TP_PHOTO_CHANNEL + }, + { + .is_touchpad = true, + .input.channel = TP_PLAY_CHANNEL + }, + { + .is_touchpad = true, + .input.channel = TP_RECORD_CHANNEL + }, + { + .is_touchpad = true, + .input.channel = TP_NETWORK_CHANNEL + }, + { + .is_touchpad = true, + .input.channel = TP_VOLUP_CHANNEL + }, + { + .is_touchpad = true, + .input.channel = TP_VOLDN_CHANNEL + } +#endif +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_button_initialize + * + * Description: + * board_button_initialize() must be called to initialize button resources. + * After that, board_buttons() may be called to collect the current state + * of all buttons or board_button_irq() may be called to register button + * interrupt handlers. + * + ****************************************************************************/ + +uint32_t board_button_initialize(void) +{ +#ifdef CONFIG_ESP32S2_TOUCH + esp32s2_configtouch(TP_PHOTO_CHANNEL, tp_config); + esp32s2_configtouch(TP_PLAY_CHANNEL, tp_config); + esp32s2_configtouch(TP_RECORD_CHANNEL, tp_config); + esp32s2_configtouch(TP_NETWORK_CHANNEL, tp_config); + esp32s2_configtouch(TP_VOLUP_CHANNEL, tp_config); + esp32s2_configtouch(TP_VOLDN_CHANNEL, tp_config); + + esp32s2_touchsetthreshold(TP_PHOTO_CHANNEL, TOUCHPAD_THRESHOLD); + esp32s2_touchsetthreshold(TP_PLAY_CHANNEL, TOUCHPAD_THRESHOLD); + esp32s2_touchsetthreshold(TP_RECORD_CHANNEL, TOUCHPAD_THRESHOLD); + esp32s2_touchsetthreshold(TP_NETWORK_CHANNEL, TOUCHPAD_THRESHOLD); + esp32s2_touchsetthreshold(TP_VOLUP_CHANNEL, TOUCHPAD_THRESHOLD); + esp32s2_touchsetthreshold(TP_VOLDN_CHANNEL, TOUCHPAD_THRESHOLD); + +#endif + esp32s2_configgpio(BUTTON_BOOT, INPUT_FUNCTION_3 | PULLUP); + return NUM_BUTTONS; +} + +/**************************************************************************** + * Name: board_buttons + * + * Description: + * After board_button_initialize() has been called, board_buttons() may be + * called to collect the state of all buttons. board_buttons() returns an + * 8-bit bit set with each bit associated with a button. See the + * BUTTON_*_BIT definitions in board.h for the meaning of each bit. + * + ****************************************************************************/ + +uint32_t board_buttons(void) +{ + uint8_t ret = 0; + bool b0; + bool b1; + int n; + + for (uint8_t btn_id = 0; btn_id < ARRAY_SIZE(g_buttons); btn_id++) + { + iinfo("Reading button %d\n", btn_id); + + const struct button_type_s button_info = g_buttons[btn_id]; + + n = 0; + + if (button_info.is_touchpad) + { + b0 = esp32s2_touchread(button_info.input.channel); + } + else + { + b0 = esp32s2_gpioread(button_info.input.gpio); + + for (int i = 0; i < 10; i++) + { + up_mdelay(1); + + b1 = esp32s2_gpioread(button_info.input.gpio); + + if (b0 == b1) + { + n++; + } + else + { + n = 0; + } + + if (3 == n) + { + break; + } + + b0 = b1; + } + } + + iinfo("b=%d n=%d\n", b0, n); + + /* Low value means that the button is pressed */ + + if (!b0) + { + ret |= (1 << btn_id); + } + } + + return ret; +} + +/**************************************************************************** + * Name: board_button_irq + * + * Description: + * board_button_irq() may be called to register an interrupt handler that + * will be called when a button is depressed or released. The ID value is + * a button enumeration value that uniquely identifies a button resource. + * See the BUTTON_* definitions in board.h for the meaning of enumeration + * value. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQBUTTONS +int board_button_irq(int id, xcpt_t irqhandler, void *arg) +{ + DEBUGASSERT(id < ARRAY_SIZE(g_buttons)); + + int ret; + struct button_type_s button_info = g_buttons[id]; + +#ifdef CONFIG_ESP32S2_TOUCH_IRQ + if (button_info.is_touchpad) + { + int channel = button_info.input.channel; + int irq = ESP32S2_TOUCHPAD2IRQ(channel); + + if (NULL != irqhandler) + { + /* Make sure the interrupt is disabled */ + + esp32s2_touchirqdisable(irq); + + esp32s2_touchregisterreleasecb(irqhandler); + ret = irq_attach(irq, irqhandler, arg); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: irq_attach() failed: %d\n", ret); + return ret; + } + + iinfo("Attach %p to touch pad %d\n", irqhandler, channel); + + iinfo("Enabling the interrupt\n"); + + esp32s2_touchirqenable(irq); + } + else + { + iinfo("Disabled interrupts from touch pad %d\n", channel); + esp32s2_touchirqdisable(irq); + } + + return OK; + } + else +#endif + { + int pin = button_info.input.gpio; + int irq = ESP32S2_PIN2IRQ(pin); + + if (NULL != irqhandler) + { + /* Make sure the interrupt is disabled */ + + esp32s2_gpioirqdisable(irq); + + ret = irq_attach(irq, irqhandler, arg); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: irq_attach() failed: %d\n", ret); + return ret; + } + + gpioinfo("Attach %p to pin %d\n", irqhandler, pin); + + gpioinfo("Enabling the interrupt\n"); + + /* Configure the interrupt for rising and falling edges */ + + esp32s2_gpioirqenable(irq, GPIO_INTR_ANYEDGE); + } + else + { + gpioinfo("Disabled interrupts from pin %d\n", pin); + esp32s2_gpioirqdisable(irq); + } + + return OK; + } +} +#endif