You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/09/12 17:49:34 UTC
(nuttx) branch master updated (c2a300d2b0 -> c5be5c2db4)
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
from c2a300d2b0 arch/arm64/imx9: Change Kconfig logic
new 1fa4e61230 espressif: Add Quadrature Encoder driver (using PCNT)
new c5be5c2db4 esp32c6-devkitc: Add Quadrature Encoder support and example configuration
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../esp32c6/boards/esp32c6-devkitc/index.rst | 10 +
arch/risc-v/src/common/espressif/Kconfig | 217 +++++++
arch/risc-v/src/common/espressif/Make.defs | 4 +
arch/risc-v/src/common/espressif/esp_qencoder.c | 657 +++++++++++++++++++++
.../src/common/espressif/esp_qencoder.h} | 41 +-
.../esp32c6/common/include/esp_board_qencoder.h} | 11 +-
boards/risc-v/esp32c6/common/src/Make.defs | 4 +
.../esp32c6/common/src/esp_board_qencoder.c} | 51 +-
.../configs/{bmp180 => qencoder}/defconfig | 12 +-
.../esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c | 14 +
10 files changed, 983 insertions(+), 38 deletions(-)
create mode 100644 arch/risc-v/src/common/espressif/esp_qencoder.c
copy arch/{arm/src/samv7/sam_qencoder.h => risc-v/src/common/espressif/esp_qencoder.h} (70%)
copy boards/{arm/stm32/common/include/board_qencoder.h => risc-v/esp32c6/common/include/esp_board_qencoder.h} (88%)
copy boards/{arm/stm32/common/src/stm32_qencoder.c => risc-v/esp32c6/common/src/esp_board_qencoder.c} (61%)
copy boards/risc-v/esp32c6/esp32c6-devkitc/configs/{bmp180 => qencoder}/defconfig (83%)
(nuttx) 02/02: esp32c6-devkitc: Add Quadrature Encoder support and example configuration
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit c5be5c2db4a36479fc9d848348e4cbd8fdc85e2c
Author: Martin Vajnar <ma...@gmail.com>
AuthorDate: Thu Sep 12 12:55:00 2024 +0200
esp32c6-devkitc: Add Quadrature Encoder support and example configuration
Signed-off-by: Martin Vajnar <ma...@gmail.com>
---
.../esp32c6/boards/esp32c6-devkitc/index.rst | 10 +++
.../esp32c6/common/include/esp_board_qencoder.h | 74 +++++++++++++++++
boards/risc-v/esp32c6/common/src/Make.defs | 4 +
.../risc-v/esp32c6/common/src/esp_board_qencoder.c | 97 ++++++++++++++++++++++
.../esp32c6-devkitc/configs/qencoder/defconfig | 58 +++++++++++++
.../esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c | 14 ++++
6 files changed, 257 insertions(+)
diff --git a/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst b/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst
index 0536d88071..c809f71bd3 100644
--- a/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst
+++ b/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst
@@ -194,6 +194,16 @@ To test it, just execute the ``pwm`` application::
pwm_main: starting output with frequency: 10000 duty: 00008000
pwm_main: stopping output
+qencoder
+---
+
+This configuration demostrates the use of Quadrature Encoder connected to pins
+GPIO10 and GPIO11. You can start measurement of pulses using the following
+command (by default, it will open ``\dev\qe0`` device and print 20 samples
+using 1 second delay)::
+
+ nsh> qe
+
rmt
---
diff --git a/boards/risc-v/esp32c6/common/include/esp_board_qencoder.h b/boards/risc-v/esp32c6/common/include/esp_board_qencoder.h
new file mode 100644
index 0000000000..15899d3063
--- /dev/null
+++ b/boards/risc-v/esp32c6/common/include/esp_board_qencoder.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+ * boards/risc-v/esp32c6/common/include/esp_board_qencoder.h
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __BOARDS_RISC_V_ESP32C6_COMMON_INCLUDE_ESP_BOARD_QENCODER_H
+#define __BOARDS_RISC_V_ESP32C6_COMMON_INCLUDE_ESP_BOARD_QENCODER_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_qencoder_initialize
+ *
+ * Description:
+ * Initialize the quadrature encoder driver for the given timer
+ *
+ ****************************************************************************/
+
+int board_qencoder_initialize(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BOARDS_RISC_V_ESP32C6_COMMON_INCLUDE_ESP_BOARD_QENCODER_H */
+
diff --git a/boards/risc-v/esp32c6/common/src/Make.defs b/boards/risc-v/esp32c6/common/src/Make.defs
index 5ca961d384..2d2a487d5a 100644
--- a/boards/risc-v/esp32c6/common/src/Make.defs
+++ b/boards/risc-v/esp32c6/common/src/Make.defs
@@ -68,6 +68,10 @@ ifeq ($(CONFIG_CL_MFRC522),y)
CSRCS += esp_board_mfrc522.c
endif
+ifeq ($(CONFIG_ESP_PCNT),y)
+ CSRCS += esp_board_qencoder.c
+endif
+
DEPPATH += --dep-path src
VPATH += :src
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src
diff --git a/boards/risc-v/esp32c6/common/src/esp_board_qencoder.c b/boards/risc-v/esp32c6/common/src/esp_board_qencoder.c
new file mode 100644
index 0000000000..b7e17b0069
--- /dev/null
+++ b/boards/risc-v/esp32c6/common/src/esp_board_qencoder.c
@@ -0,0 +1,97 @@
+/****************************************************************************
+ * boards/risc-v/esp32c6/common/src/esp_board_qencoder.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 <nuttx/config.h>
+
+#include <errno.h>
+#include <debug.h>
+#include <stdio.h>
+
+#include <nuttx/sensors/qencoder.h>
+#include <arch/board/board.h>
+
+#include "espressif/esp_qencoder.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_qencoder_initialize
+ *
+ * Description:
+ * Initialize the quadrature encoder driver
+ *
+ ****************************************************************************/
+
+int board_qencoder_initialize(void)
+{
+ int ret;
+ char devpath[12];
+ int devno = 0;
+
+ /* Initialize a quadrature encoder interface. */
+#ifdef CONFIG_ESP_PCNT_U0_QE
+ snprintf(devpath, sizeof(devpath), "/dev/qe%d", devno++);
+ ret = esp_qeinitialize(devpath, 0);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: esp_qeinitialize failed: %d\n", ret);
+ return ret;
+ }
+#endif
+
+#ifdef CONFIG_ESP_PCNT_U1_QE
+ snprintf(devpath, sizeof(devpath), "/dev/qe%d", devno++);
+ ret = esp_qeinitialize(devpath, 1);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: esp_qeinitialize failed: %d\n", ret);
+ return ret;
+ }
+#endif
+
+#ifdef CONFIG_ESP_PCNT_U2_QE
+ snprintf(devpath, sizeof(devpath), "/dev/qe%d", devno++);
+ ret = esp_qeinitialize(devpath, 2);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: esp_qeinitialize failed: %d\n", ret);
+ return ret;
+ }
+#endif
+
+#ifdef CONFIG_ESP_PCNT_U3_QE
+ snprintf(devpath, sizeof(devpath), "/dev/qe%d", devno++);
+ ret = esp_qeinitialize(devpath, 3);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: esp_qeinitialize failed: %d\n", ret);
+ return ret;
+ }
+#endif
+
+ return ret;
+}
+
diff --git a/boards/risc-v/esp32c6/esp32c6-devkitc/configs/qencoder/defconfig b/boards/risc-v/esp32c6/esp32c6-devkitc/configs/qencoder/defconfig
new file mode 100644
index 0000000000..e93c8625c4
--- /dev/null
+++ b/boards/risc-v/esp32c6/esp32c6-devkitc/configs/qencoder/defconfig
@@ -0,0 +1,58 @@
+#
+# 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_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="esp32c6-devkitc"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_ESP32C6_DEVKITC=y
+CONFIG_ARCH_CHIP="esp32c6"
+CONFIG_ARCH_CHIP_ESP32C6=y
+CONFIG_ARCH_CHIP_ESP32C6WROOM1=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=15000
+CONFIG_BUILTIN=y
+CONFIG_DEV_ZERO=y
+CONFIG_ESPRESSIF_ESP32C6=y
+CONFIG_ESP_PCNT=y
+CONFIG_ESP_PCNT_U0=y
+CONFIG_ESP_PCNT_U0_CH0_EDGE_PIN=10
+CONFIG_ESP_PCNT_U0_CH1_LEVEL_PIN=11
+CONFIG_ESP_PCNT_U0_FILTER_EN=y
+CONFIG_EXAMPLES_QENCODER=y
+CONFIG_EXAMPLES_QENCODER_DELAY=1000
+CONFIG_EXAMPLES_QENCODER_NSAMPLES=20
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_STRERROR=y
+CONFIG_PREALLOC_TIMERS=0
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_BACKTRACE=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SENSORS=y
+CONFIG_SENSORS_QENCODER=y
+CONFIG_START_DAY=29
+CONFIG_START_MONTH=11
+CONFIG_START_YEAR=2019
+CONFIG_SYSTEM_DUMPSTACK=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_UART0_SERIAL_CONSOLE=y
diff --git a/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c b/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c
index b197add1f9..fc7c9fde7d 100644
--- a/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c
+++ b/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c
@@ -93,6 +93,10 @@
# include "esp_board_mcpwm.h"
#endif
+#ifdef CONFIG_ESP_PCNT_AS_QE
+# include "esp_board_qencoder.h"
+#endif
+
#include "esp32c6-devkitc.h"
/****************************************************************************
@@ -356,6 +360,16 @@ int esp_bringup(void)
}
#endif
+#ifdef CONFIG_SENSORS_QENCODER
+ /* Initialize and register the qencoder driver */
+
+ ret = board_qencoder_initialize();
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: board_qencoder_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.
(nuttx) 01/02: espressif: Add Quadrature Encoder driver (using PCNT)
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 1fa4e61230bc6d0a35917dd05ed1d5babfe5a533
Author: Martin Vajnar <ma...@gmail.com>
AuthorDate: Thu Sep 5 11:22:39 2024 +0200
espressif: Add Quadrature Encoder driver (using PCNT)
Signed-off-by: Martin Vajnar <ma...@gmail.com>
Co-authored-by: Pavel Pisa <pi...@fel.cvut.cz>
---
arch/risc-v/src/common/espressif/Kconfig | 217 ++++++++
arch/risc-v/src/common/espressif/Make.defs | 4 +
arch/risc-v/src/common/espressif/esp_qencoder.c | 657 ++++++++++++++++++++++++
arch/risc-v/src/common/espressif/esp_qencoder.h | 82 +++
4 files changed, 960 insertions(+)
diff --git a/arch/risc-v/src/common/espressif/Kconfig b/arch/risc-v/src/common/espressif/Kconfig
index 5f3ceba81c..c99ea1d7e4 100644
--- a/arch/risc-v/src/common/espressif/Kconfig
+++ b/arch/risc-v/src/common/espressif/Kconfig
@@ -486,6 +486,223 @@ config ESP_MCPWM
Enable support for timer capture and motor control using
the Motor Control PWM peripheral.
+config ESP_PCNT
+ bool "Pulse Counter (PCNT / QE) Module"
+ default n
+ depends on ESPRESSIF_ESP32H2 || ESPRESSIF_ESP32C6
+ ---help---
+ Pulse Counter is currently used to implement Quadrature
+ Encoder.
+
+menu "Pulse Counter (PCNT) Configuration"
+ depends on ESP_PCNT
+
+config ESP_PCNT_AS_QE
+ bool
+ default n
+
+config ESP_PCNT_U0
+ bool "Enable PCNT Unit 0"
+ default n
+
+if ESP_PCNT_U0
+
+config ESP_PCNT_U0_QE
+ bool "Use this PCNT Unit as Quadrature Encoder"
+ default y
+ select ESP_PCNT_AS_QE
+
+config ESP_PCNT_U0_CH0_EDGE_PIN
+ int "PCNT_U0 CH0 Edge/Pulse Pin Number"
+ default 0
+ range -1 39
+
+config ESP_PCNT_U0_CH0_LEVEL_PIN
+ int "PCNT_U0 CH0 Level/Control Pin Number"
+ default 4
+ range -1 39
+ depends on !ESP_PCNT_U0_QE
+
+config ESP_PCNT_U0_CH1_EDGE_PIN
+ int "PCNT_U0 CH1 Edge/Pulse Pin Number"
+ default 0
+ range -1 39
+ depends on !ESP_PCNT_U0_QE
+
+config ESP_PCNT_U0_CH1_LEVEL_PIN
+ int "PCNT_U0 CH1 Level/Control Pin Number"
+ default 4
+ range -1 39
+
+config ESP_PCNT_U0_FILTER_EN
+ bool "Enable Glitch Filter for this PCNT Unit"
+ default n
+
+if ESP_PCNT_U0_FILTER_EN
+
+config ESP_PCNT_U0_FILTER_THRES
+ int "PCNT_U0 Filter Threshold value"
+ default 5
+ ---help---
+ If a pulse is shorter than this number of APB_CLK clock cycles
+ then it will not be considered as a valid pulse.
+
+endif # ESP_PCNT_U0_FILTER_EN
+
+endif # ESP_PCNT_U0
+
+config ESP_PCNT_U1
+ bool "Enable PCNT Unit 1"
+ default n
+
+if ESP_PCNT_U1
+
+config ESP_PCNT_U1_QE
+ bool "Use this PCNT Unit as Quadrature Encoder"
+ default y
+ select ESP_PCNT_AS_QE
+
+config ESP_PCNT_U1_CH0_EDGE_PIN
+ int "PCNT_U1 CH0 Edge/Pulse Pin Number"
+ default 0
+ range -1 39
+
+config ESP_PCNT_U1_CH0_LEVEL_PIN
+ int "PCNT_U1 CH0 Level/Control Pin Number"
+ default 4
+ range -1 39
+ depends on !ESP_PCNT_U1_QE
+
+config ESP_PCNT_U1_CH1_EDGE_PIN
+ int "PCNT_U1 CH1 Edge/Pulse Pin Number"
+ default 0
+ range -1 39
+ depends on !ESP_PCNT_U1_QE
+
+config ESP_PCNT_U1_CH1_LEVEL_PIN
+ int "PCNT_U1 CH1 Level/Control Pin Number"
+ default 4
+ range -1 39
+
+config ESP_PCNT_U1_FILTER_EN
+ bool "Enable Glitch Filter for this PCNT Unit"
+ default n
+
+if ESP_PCNT_U1_FILTER_EN
+
+config ESP_PCNT_U1_FILTER_THRES
+ int "PCNT_U1 Filter Threshold value"
+ default 5
+ ---help---
+ If a pulse is shorter than this number of APB_CLK clock cycles
+ then it will not be considered as a valid pulse.
+
+endif # ESP_PCNT_U1_FILTER_EN
+
+endif # ESP_PCNT_U1
+
+config ESP_PCNT_U2
+ bool "Enable PCNT Unit 2"
+ default n
+
+if ESP_PCNT_U2
+
+config ESP_PCNT_U2_QE
+ bool "Use this PCNT Unit as Quadrature Encoder"
+ default y
+ select ESP_PCNT_AS_QE
+
+config ESP_PCNT_U2_CH0_EDGE_PIN
+ int "PCNT_U2 CH0 Edge/Pulse Pin Number"
+ default 0
+ range -1 39
+
+config ESP_PCNT_U2_CH0_LEVEL_PIN
+ int "PCNT_U2 CH0 Level/Control Pin Number"
+ default 4
+ range -1 39
+ depends on !ESP_PCNT_U2_QE
+
+config ESP_PCNT_U2_CH1_EDGE_PIN
+ int "PCNT_U2 CH1 Edge/Pulse Pin Number"
+ default 0
+ range -1 39
+ depends on !ESP_PCNT_U2_QE
+
+config ESP_PCNT_U2_CH1_LEVEL_PIN
+ int "PCNT_U2 CH1 Level/Control Pin Number"
+ default 4
+ range -1 39
+
+config ESP_PCNT_U2_FILTER_EN
+ bool "Enable Glitch Filter for this PCNT Unit"
+ default n
+
+if ESP_PCNT_U2_FILTER_EN
+
+config ESP_PCNT_U2_FILTER_THRES
+ int "PCNT_U2 Filter Threshold value"
+ default 5
+ ---help---
+ If a pulse is shorter than this number of APB_CLK clock cycles
+ then it will not be considered as a valid pulse.
+
+endif # ESP_PCNT_U2_FILTER_EN
+
+endif # ESP_PCNT_U2
+
+config ESP_PCNT_U3
+ bool "Enable PCNT Unit 3"
+ default n
+
+if ESP_PCNT_U3
+
+config ESP_PCNT_U3_QE
+ bool "Use this PCNT Unit as Quadrature Encoder"
+ default y
+ select ESP_PCNT_AS_QE
+
+config ESP_PCNT_U3_CH0_EDGE_PIN
+ int "PCNT_U3 CH0 Edge/Pulse Pin Number"
+ default 0
+ range -1 39
+
+config ESP_PCNT_U3_CH0_LEVEL_PIN
+ int "PCNT_U3 CH0 Level/Control Pin Number"
+ default 4
+ range -1 39
+ depends on !ESP_PCNT_U3_QE
+
+config ESP_PCNT_U3_CH1_EDGE_PIN
+ int "PCNT_U3 CH1 Edge/Pulse Pin Number"
+ default 0
+ range -1 39
+ depends on !ESP_PCNT_U3_QE
+
+config ESP_PCNT_U3_CH1_LEVEL_PIN
+ int "PCNT_U3 CH1 Level/Control Pin Number"
+ default 4
+ range -1 39
+
+config ESP_PCNT_U3_FILTER_EN
+ bool "Enable Glitch Filter for this PCNT Unit"
+ default n
+
+if ESP_PCNT_U3_FILTER_EN
+
+config ESP_PCNT_U3_FILTER_THRES
+ int "PCNT_U3 Filter Threshold value"
+ default 5
+ ---help---
+ If a pulse is shorter than this number of APB_CLK clock cycles
+ then it will not be considered as a valid pulse.
+
+endif # ESP_PCNT_U3_FILTER_EN
+
+endif # ESP_PCNT_U3
+
+endmenu # ESP_PCNT
+
endmenu # Peripheral Support
menu "Wi-Fi Configuration"
diff --git a/arch/risc-v/src/common/espressif/Make.defs b/arch/risc-v/src/common/espressif/Make.defs
index 651a45337d..95c25a01f9 100644
--- a/arch/risc-v/src/common/espressif/Make.defs
+++ b/arch/risc-v/src/common/espressif/Make.defs
@@ -77,6 +77,10 @@ ifeq ($(CONFIG_ESPRESSIF_LEDC),y)
CHIP_CSRCS += esp_ledc.c
endif
+ifeq ($(CONFIG_ESP_PCNT_AS_QE),y)
+ CHIP_CSRCS += esp_qencoder.c
+endif
+
ifeq ($(CONFIG_ESPRESSIF_USBSERIAL),y)
CHIP_CSRCS += esp_usbserial.c
endif
diff --git a/arch/risc-v/src/common/espressif/esp_qencoder.c b/arch/risc-v/src/common/espressif/esp_qencoder.c
new file mode 100644
index 0000000000..b7649248fe
--- /dev/null
+++ b/arch/risc-v/src/common/espressif/esp_qencoder.c
@@ -0,0 +1,657 @@
+/****************************************************************************
+ * arch/risc-v/src/common/espressif/esp_qencoder.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 <nuttx/config.h>
+
+#include <stdint.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+#include <inttypes.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/spinlock.h>
+#include <nuttx/sensors/qencoder.h>
+
+#include <arch/board/board.h>
+
+#include "soc/gpio_sig_map.h"
+#include "periph_ctrl.h"
+#include "esp_gpio.h"
+#include "hal/pcnt_ll.h"
+
+#ifdef CONFIG_SENSORS_QENCODER
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Input filter *************************************************************/
+
+#ifdef CONFIG_ESP_PCNT_U0_QE
+# ifndef CONFIG_ESP_PCNT_U0_FILTER_EN
+# warning "Glitch Filter is recommended for Quadrature Encoder on PCNT_U0"
+# endif
+#endif
+
+#ifdef CONFIG_ESP_PCNT_U1_QE
+# ifndef CONFIG_ESP_PCNT_U1_FILTER_EN
+# warning "Glitch Filter is recommended for Quadrature Encoder on PCNT_U1"
+# endif
+#endif
+
+#ifdef CONFIG_ESP_PCNT_U2_QE
+# ifndef CONFIG_ESP_PCNT_U2_FILTER_EN
+# warning "Glitch Filter is recommended for Quadrature Encoder on PCNT_U2"
+# endif
+#endif
+
+#ifdef CONFIG_ESP_PCNT_U3_QE
+# ifndef CONFIG_ESP_PCNT_U3_FILTER_EN
+# warning "Glitch Filter is recommended for Quadrature Encoder on PCNT_U3"
+# endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* Constant configuration structure that is retained in FLASH */
+
+struct esp_qeconfig_s
+{
+ uint8_t pcntid; /* PCNT ID {0,1,2,3} */
+ uint8_t ch0_gpio; /* Channel 0 gpio pin (Edge/Pulse) */
+ uint8_t ch1_gpio; /* Channel 1 gpio pin (Level/Ctrl) */
+ uint32_t ch0_pulse_sig; /* ch0 pulse signal index */
+ uint32_t ch0_ctrl_sig; /* ch0 ctrl signal index */
+ uint32_t ch1_pulse_sig; /* ch1 pulse signal index */
+ uint32_t ch1_ctrl_sig; /* ch1 ctrl signal index */
+ uint16_t filter_thres; /* Filter threshold for this PCNT Unit */
+};
+
+/* NOTE: we are using Quadrature Encoder in X4 mode on ESP PCNT, then
+ * instead of using 'pulse_gpio' and 'ctrl_gpio' names, we only use ch0_gpio
+ * and ch1_gpio names. It avoid confusion, since the same signal that is used
+ * on pin 'pulse' of CH0 is also connected to 'ctrl' pin of the CH1 and
+ * 'ctrl' pin of CH0 is also connected on 'pulse' pin of CH1.
+ */
+
+/* Overall, RAM-based state structure */
+
+struct qe_dev_lowerhalf_s
+{
+ /* The first field of this state structure must be a pointer to the
+ * lower-half callback structure:
+ */
+
+ const struct qe_ops_s *ops; /* Lower half callback structure */
+
+ /* ESP driver-specific fields: */
+
+ const struct esp_qeconfig_s *config; /* static configuration */
+ bool inuse; /* True: The lower-half driver is
+ * in-use */
+ struct pcnt_dev_t *dev; /* Device handle */
+ volatile int32_t position; /* The current position offset */
+ spinlock_t lock; /* Device specific lock. */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Interrupt handling */
+
+#if 0 /* FIXME: To be implemented */
+static int esp_interrupt(int irq, void *context, void *arg);
+#endif
+
+/* Lower-half Quadrature Encoder Driver Methods */
+
+static int esp_setup(struct qe_lowerhalf_s *lower);
+static int esp_shutdown(struct qe_lowerhalf_s *lower);
+static int esp_position(struct qe_lowerhalf_s *lower,
+ int32_t *pos);
+static int esp_setposmax(struct qe_lowerhalf_s *lower, uint32_t pos);
+static int esp_reset(struct qe_lowerhalf_s *lower);
+static int esp_setindex(struct qe_lowerhalf_s *lower, uint32_t pos);
+static int esp_ioctl(struct qe_lowerhalf_s *lower, int cmd,
+ unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* The lower half callback structure */
+
+static const struct qe_ops_s g_qecallbacks =
+{
+ .setup = esp_setup,
+ .shutdown = esp_shutdown,
+ .position = esp_position,
+ .setposmax = esp_setposmax,
+ .reset = esp_reset,
+ .setindex = esp_setindex,
+ .ioctl = esp_ioctl,
+};
+
+/* Per-pcnt state structures */
+
+#ifdef CONFIG_ESP_PCNT_U0_QE
+static const struct esp_qeconfig_s g_pcnt0config =
+{
+ .pcntid = 0,
+ .ch0_gpio = CONFIG_ESP_PCNT_U0_CH0_EDGE_PIN,
+ .ch1_gpio = CONFIG_ESP_PCNT_U0_CH1_LEVEL_PIN,
+ .ch0_pulse_sig = PCNT_SIG_CH0_IN0_IDX,
+ .ch1_pulse_sig = PCNT_SIG_CH1_IN0_IDX,
+ .ch0_ctrl_sig = PCNT_CTRL_CH0_IN0_IDX,
+ .ch1_ctrl_sig = PCNT_CTRL_CH1_IN0_IDX,
+ .filter_thres = CONFIG_ESP_PCNT_U0_FILTER_THRES,
+};
+
+static struct qe_dev_lowerhalf_s g_pcnt0lower =
+{
+ .ops = &g_qecallbacks,
+ .config = &g_pcnt0config,
+ .inuse = false,
+ .dev = PCNT_LL_GET_HW(0),
+};
+#endif
+
+#ifdef CONFIG_ESP_PCNT_U1_QE
+static const struct esp_qeconfig_s g_pcnt1config =
+{
+ .pcntid = 1,
+ .ch0_gpio = CONFIG_ESP_PCNT_U1_CH0_EDGE_PIN,
+ .ch1_gpio = CONFIG_ESP_PCNT_U1_CH1_LEVEL_PIN,
+ .ch0_pulse_sig = PCNT_SIG_CH0_IN1_IDX,
+ .ch1_pulse_sig = PCNT_SIG_CH1_IN1_IDX,
+ .ch0_ctrl_sig = PCNT_CTRL_CH0_IN1_IDX,
+ .ch1_ctrl_sig = PCNT_CTRL_CH1_IN1_IDX,
+ .filter_thres = CONFIG_ESP_PCNT_U1_FILTER_THRES,
+};
+
+static struct qe_dev_lowerhalf_s g_pcnt1lower =
+{
+ .ops = &g_qecallbacks,
+ .config = &g_pcnt1config,
+ .inuse = false,
+ .dev = PCNT_LL_GET_HW(0),
+};
+#endif
+
+#ifdef CONFIG_ESP_PCNT_U2_QE
+static const struct esp_qeconfig_s g_pcnt2config =
+{
+ .pcntid = 2,
+ .ch0_gpio = CONFIG_ESP_PCNT_U2_CH0_EDGE_PIN,
+ .ch1_gpio = CONFIG_ESP_PCNT_U2_CH1_LEVEL_PIN,
+ .ch0_pulse_sig = PCNT_SIG_CH0_IN2_IDX,
+ .ch1_pulse_sig = PCNT_SIG_CH1_IN2_IDX,
+ .ch0_ctrl_sig = PCNT_CTRL_CH0_IN2_IDX,
+ .ch1_ctrl_sig = PCNT_CTRL_CH1_IN2_IDX,
+ .filter_thres = CONFIG_ESP_PCNT_U2_FILTER_THRES,
+};
+
+static struct qe_dev_lowerhalf_s g_pcnt2lower =
+{
+ .ops = &g_qecallbacks,
+ .config = &g_pcnt2config,
+ .inuse = false,
+ .dev = PCNT_LL_GET_HW(0),
+};
+#endif
+
+#ifdef CONFIG_ESP_PCNT_U3_QE
+static const struct esp_qeconfig_s g_pcnt3config =
+{
+ .pcntid = 3,
+ .ch0_gpio = CONFIG_ESP_PCNT_U3_CH0_EDGE_PIN,
+ .ch1_gpio = CONFIG_ESP_PCNT_U3_CH1_LEVEL_PIN,
+ .ch0_pulse_sig = PCNT_SIG_CH0_IN3_IDX,
+ .ch1_pulse_sig = PCNT_SIG_CH1_IN3_IDX,
+ .ch0_ctrl_sig = PCNT_CTRL_CH0_IN3_IDX,
+ .ch1_ctrl_sig = PCNT_CTRL_CH1_IN3_IDX,
+ .filter_thres = CONFIG_ESP_PCNT_U3_FILTER_THRES,
+};
+
+static struct qe_dev_lowerhalf_s g_pcnt3lower =
+{
+ .ops = &g_qecallbacks,
+ .config = &g_pcnt3config,
+ .inuse = false,
+ .dev = PCNT_LL_GET_HW(0),
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_interrupt
+ *
+ * Description:
+ * Common timer interrupt handling. NOTE: Only 16-bit timers require timer
+ * interrupts.
+ *
+ ****************************************************************************/
+
+#if 0 /* FIXME: To be implemented */
+static int esp_interrupt(int irq, void *context, void *arg)
+{
+ struct qe_dev_lowerhalf_s *priv = (struct qe_dev_lowerhalf_s *)arg;
+ uint16_t regval;
+
+ DEBUGASSERT(priv != NULL);
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: esp_setup
+ *
+ * Description:
+ * This method is called when the driver is opened. The lower half driver
+ * should configure and initialize the device so that it is ready for use.
+ * The initial position value should be zero. *
+ *
+ * Input Parameters:
+ * lower - Pointer to Lower half driver structure
+ *
+ * Returned Value:
+ * Zero on success; A negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+static int esp_setup(struct qe_lowerhalf_s *lower)
+{
+ DEBUGASSERT(lower);
+
+ struct qe_dev_lowerhalf_s *priv = (struct qe_dev_lowerhalf_s *)lower;
+ irqstate_t flags;
+
+ /* Protected access to the registers */
+
+ flags = spin_lock_irqsave(&priv->lock);
+
+ /* Make sure that it is available */
+
+ if (priv->inuse)
+ {
+ snerr("ERROR: PCNT%d is in-use\n", priv->config->pcntid);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return -EBUSY;
+ }
+
+ /* Disable interrupts */
+
+ pcnt_ll_enable_intr(priv->dev, priv->config->pcntid, false);
+
+ /* Disable all events */
+
+ pcnt_ll_disable_all_events(priv->dev, priv->config->pcntid);
+
+ /* Configure the limits range PCNT_CNT_L_LIM | PCNT_CNT_H_LIM */
+
+ pcnt_ll_set_high_limit_value(priv->dev, priv->config->pcntid, INT16_MAX);
+ pcnt_ll_set_low_limit_value(priv->dev, priv->config->pcntid, INT16_MIN);
+
+ /* Setup POS/NEG/LCTRL/HCTRL/FILTER modes */
+
+ pcnt_ll_set_glitch_filter_thres(priv->dev,
+ priv->config->pcntid,
+ priv->config->filter_thres);
+ pcnt_ll_enable_glitch_filter(priv->dev,
+ priv->config->pcntid,
+ true);
+
+ pcnt_ll_set_edge_action(priv->dev,
+ priv->config->pcntid,
+ 0,
+ PCNT_CHANNEL_EDGE_ACTION_DECREASE,
+ PCNT_CHANNEL_EDGE_ACTION_INCREASE);
+ pcnt_ll_set_level_action(priv->dev,
+ priv->config->pcntid,
+ 0,
+ PCNT_CHANNEL_LEVEL_ACTION_KEEP,
+ PCNT_CHANNEL_LEVEL_ACTION_INVERSE);
+
+ pcnt_ll_set_edge_action(priv->dev,
+ priv->config->pcntid,
+ 1,
+ PCNT_CHANNEL_EDGE_ACTION_INCREASE,
+ PCNT_CHANNEL_EDGE_ACTION_DECREASE);
+ pcnt_ll_set_level_action(priv->dev,
+ priv->config->pcntid,
+ 1,
+ PCNT_CHANNEL_LEVEL_ACTION_KEEP,
+ PCNT_CHANNEL_LEVEL_ACTION_INVERSE);
+
+ /* Clear the Reset bit to enable the Pulse Counter */
+
+ pcnt_ll_clear_count(priv->dev, priv->config->pcntid);
+ pcnt_ll_start_count(priv->dev, priv->config->pcntid);
+
+ /* Mark as being used to prevent double opening of the same unit which
+ * would reset position
+ */
+
+ priv->inuse = true;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: esp_shutdown
+ *
+ * Description:
+ * This method is called when the driver is closed. The lower half driver
+ * should stop data collection, free any resources, disable timer hardware,
+ * and put the system into the lowest possible power usage state
+ *
+ * Input Parameters:
+ * lower - Pointer to Lower half driver structure
+ *
+ * Returned Value:
+ * Zero on success; A negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+static int esp_shutdown(struct qe_lowerhalf_s *lower)
+{
+ DEBUGASSERT(lower);
+
+ struct qe_dev_lowerhalf_s *priv = (struct qe_dev_lowerhalf_s *)lower;
+ irqstate_t flags;
+
+ /* Protected access to the registers */
+
+ flags = spin_lock_irqsave(&priv->lock);
+
+ /* Disable interrupts */
+
+ pcnt_ll_enable_intr(priv->dev, priv->config->pcntid, false);
+
+ /* Disable all events */
+
+ pcnt_ll_disable_all_events(priv->dev, priv->config->pcntid);
+
+ /* Make sure initial position is 0 */
+
+ priv->position = 0;
+
+ priv->inuse = false;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: esp_position
+ *
+ * Description:
+ * Return the current position measurement.
+ *
+ * Input Parameters:
+ * lower - Pointer to Lower half driver structure
+ * pos - Pointer to updated position measurement
+ *
+ * Returned Value:
+ * Zero on success; A negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+static int esp_position(struct qe_lowerhalf_s *lower, int32_t *pos)
+{
+ DEBUGASSERT(lower && pos);
+
+ struct qe_dev_lowerhalf_s *priv = (struct qe_dev_lowerhalf_s *)lower;
+ irqstate_t flags;
+ int32_t position;
+ int16_t count;
+
+ flags = spin_lock_irqsave(&priv->lock);
+
+ position = priv->position;
+ count = (int16_t)(pcnt_ll_get_count(priv->dev,
+ priv->config->pcntid) & 0xffff);
+
+ /* Update the position measurement */
+
+ *pos = position + count;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: esp_setposmax
+ *
+ * Description:
+ * Set the maximum encoder position.
+ *
+ * Input Parameters:
+ * lower - Pointer to Lower half driver structure
+ * pos - Requested maximum position
+ *
+ * Returned Value:
+ * Zero on success; A negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+static int esp_setposmax(struct qe_lowerhalf_s *lower, uint32_t pos)
+{
+ return -ENOTTY;
+}
+
+/****************************************************************************
+ * Name: esp_reset
+ *
+ * Description:
+ * Reset the position measurement to zero.
+ *
+ * Input Parameters:
+ * lower - Pointer to Lower half driver structure
+ *
+ * Returned Value:
+ * Zero on success; A negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+static int esp_reset(struct qe_lowerhalf_s *lower)
+{
+ DEBUGASSERT(lower);
+
+ struct qe_dev_lowerhalf_s *priv = (struct qe_dev_lowerhalf_s *)lower;
+ irqstate_t flags;
+ uint32_t regval;
+
+ sninfo("Resetting position to zero\n");
+
+ /* Reset this Pulse Counter Unit. */
+
+ flags = spin_lock_irqsave(&priv->lock);
+
+ /* Reset RST bit and clear RST bit to enable counting again */
+
+ pcnt_ll_clear_count(priv->dev, priv->config->pcntid);
+
+ priv->position = 0;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: esp_setindex
+ *
+ * Description:
+ * Set the index pin position
+ *
+ * Input Parameters:
+ * lower - Pointer to Lower half driver structure
+ * pos - Requested index position
+ *
+ * Returned Value:
+ * Zero on success; A negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+static int esp_setindex(struct qe_lowerhalf_s *lower, uint32_t pos)
+{
+ return -ENOTTY;
+}
+
+/****************************************************************************
+ * Name: esp_ioctl
+ *
+ * Description:
+ * Lower-half logic may support platform-specific ioctl commands
+ *
+ * Input Parameters:
+ * lower - Pointer to Lower half driver structure
+ * cmd - Ioctl command
+ * arg - command argument
+ *
+ * Returned Value:
+ * Zero on success; A negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+static int esp_ioctl(struct qe_lowerhalf_s *lower, int cmd,
+ unsigned long arg)
+{
+ /* No ioctl commands supported */
+
+ /* TODO add an IOCTL to control the encoder pulse count prescaler */
+
+ return -ENOTTY;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_qeinitialize
+ *
+ * Description:
+ * Initialize a quadrature encoder interface. This function must be
+ * called from board-specific logic.
+ *
+ * Input Parameters:
+ * devpath - The full path to the driver to register. E.g., "/dev/qe0"
+ * pcnt - The PCNT number to used. 'pcnt' must be an element of
+ * {0,1,2,3}
+ *
+ * Returned Value:
+ * Zero on success; A negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+int esp_qeinitialize(const char *devpath, int pcnt)
+{
+ struct qe_dev_lowerhalf_s *priv;
+ int ret;
+
+ /* Find the pre-allocated timer state structure corresponding to this
+ * timer
+ */
+
+ switch (pcnt)
+ {
+#ifdef CONFIG_ESP_PCNT_U0_QE
+ case 0:
+ priv = &g_pcnt0lower;
+ break;
+#endif
+#ifdef CONFIG_ESP_PCNT_U1_QE
+ case 1:
+ priv = &g_pcnt1lower;
+ break;
+#endif
+#ifdef CONFIG_ESP_PCNT_U2_QE
+ case 2:
+ priv = &g_pcnt2lower;
+ break;
+#endif
+#ifdef CONFIG_ESP_PCNT_U3_QE
+ case 3:
+ priv = &g_pcnt3lower;
+ break;
+#endif
+ default:
+ priv = NULL;
+ }
+
+ if (priv == NULL)
+ {
+ snerr("ERROR: PCNT%d support not configured\n", pcnt);
+ return -ENXIO;
+ }
+
+ /* Register the upper-half driver */
+
+ ret = qe_register(devpath, (struct qe_lowerhalf_s *)priv);
+ if (ret < 0)
+ {
+ snerr("ERROR: qe_register failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Configure GPIO pins as Input with Pull-Up enabled */
+
+ esp_configgpio(priv->config->ch0_gpio, INPUT_FUNCTION | PULLUP);
+ esp_configgpio(priv->config->ch1_gpio, INPUT_FUNCTION | PULLUP);
+
+ /* Connect Channel A (ch0_gpio) and Channel B (ch1_gpio) crossed for X4 */
+
+ esp_gpio_matrix_in(priv->config->ch0_gpio,
+ priv->config->ch0_pulse_sig, 0);
+ esp_gpio_matrix_in(priv->config->ch1_gpio,
+ priv->config->ch0_ctrl_sig, 0);
+
+ esp_gpio_matrix_in(priv->config->ch1_gpio,
+ priv->config->ch1_pulse_sig, 0);
+ esp_gpio_matrix_in(priv->config->ch0_gpio,
+ priv->config->ch1_ctrl_sig, 0);
+
+ /* Enable the PCNT Clock and Reset the peripheral */
+
+ periph_module_enable(PERIPH_PCNT_MODULE);
+ periph_module_reset(PERIPH_PCNT_MODULE);
+
+ return OK;
+}
+
+#endif /* CONFIG_SENSORS_QENCODER */
diff --git a/arch/risc-v/src/common/espressif/esp_qencoder.h b/arch/risc-v/src/common/espressif/esp_qencoder.h
new file mode 100644
index 0000000000..7fadc0f715
--- /dev/null
+++ b/arch/risc-v/src/common/espressif/esp_qencoder.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+ * arch/risc-v/src/common/espressif/esp_qencoder.h
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISC_V_SRC_COMMON_ESPRESSIF_ESP_QENCODER_H
+#define __ARCH_RISC_V_SRC_COMMON_ESPRESSIF_ESP_QENCODER_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+#ifdef CONFIG_SENSORS_QENCODER
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/* Timer devices may be used for different purposes. One special purpose is
+ * as a quadrature encoder input device. If CONFIG_ESP_PCNT_Un is defined
+ * then the CONFIG_ESP_PCNT_Un_QE must also be defined to indicate that
+ * pcnt "n" is intended to be used for as a quadrature encoder.
+ */
+
+#ifndef CONFIG_ESP_PCNT_U0
+# undef CONFIG_ESP_PCNT_U0_QE
+#endif
+#ifndef CONFIG_ESP_PCNT_U1
+# undef CONFIG_ESP_PCNT_U1_QE
+#endif
+#ifndef CONFIG_ESP_PCNT_U2
+# undef CONFIG_ESP_PCNT_U2_QE
+#endif
+#ifndef CONFIG_ESP_PCNT_U3
+# undef CONFIG_ESP_PCNT_U3_QE
+#endif
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp_qeinitialize
+ *
+ * Description:
+ * Initialize a quadrature encoder interface. This function must be called
+ * from board-specific logic..
+ *
+ * Input Parameters:
+ * devpath - The full path to the driver to register. E.g., "/dev/qe0"
+ * pcnt - The PCNT number to used. 'tim' must be an element of
+ * {0,1,2,3}
+ *
+ * Returned Value:
+ * Zero on success; A negated errno value is returned on failure.
+ *
+ ****************************************************************************/
+
+int esp_qeinitialize(const char *devpath, int pcnt);
+
+#endif /* CONFIG_SENSORS_QENCODER */
+#endif /* __ARCH_RISC_V_SRC_COMMON_ESPRESSIF_ESP_QENCODER_H */
+