diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/configs/lcdnsh/defconfig b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/configs/lcdnsh/defconfig new file mode 100755 index 000000000..7083d8a39 --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/configs/lcdnsh/defconfig @@ -0,0 +1,109 @@ +# +# 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_ADD_NUTTX_FETURES=y +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="xidatong" +CONFIG_ARCH_BOARD_XIDATONG=y +CONFIG_ARCH_CHIP="imxrt" +CONFIG_ARCH_CHIP_IMXRT=y +CONFIG_ARCH_CHIP_MIMXRT1052CVL5B=y +CONFIG_ARCH_INTERRUPTSTACK=10240 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_ARMV7M_USEBASEPRI=y +CONFIG_BOARD_LOOPSPERMSEC=104926 +CONFIG_BUILTIN=y +CONFIG_CLOCK_MONOTONIC=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_IMXRT_GPIO_IRQ=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_IMXRT_LPUART1=y +CONFIG_INTELHEX_BINARY=y +CONFIG_LPUART1_SERIAL_CONSOLE=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_RAM_SIZE=524288 +CONFIG_RAM_START=0x20200000 +CONFIG_RAW_BINARY=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=14 +CONFIG_START_MONTH=3 +CONFIG_SYSTEM_NSH=y +CONFIG_DEV_GPIO=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_CMD_HISTORY_LEN=100 +CONFIG_READLINE_CMD_HISTORY_LINELEN=120 +CONFIG_READLINE_TABCOMPLETION=y + +CONFIG_USER_ENTRYPOINT="nsh_main" + +CONFIG_IMXRT_LPI2C=y +CONFIG_IMXRT_LCD=y +CONFIG_IMXRT_LPI2C1=y +CONFIG_LPI2C1_BUSYIDLE=0 +CONFIG_LPI2C1_FILTSCL=0 +CONFIG_LPI2C1_FILTSDA=0 +CONFIG_IMXRT_GPIO2_16_31_IRQ=y + +CONFIG_IMXRT_LPI2C_DYNTIMEO=y +CONFIG_IMXRT_LPI2C_DYNTIMEO_USECPERBYTE=500 +CONFIG_IMXRT_LPI2C_DYNTIMEO_STARTSTOP=1000 +CONFIG_IMXRT_LPI2C_TIMEOSEC=0 +CONFIG_IMXRT_LCD_VIDEO_PLL_FREQ=92000000 +CONFIG_IMXRT_LCD_VRAMBASE=0x80000000 +CONFIG_IMXRT_LCD_REFRESH_FREQ=60 +CONFIG_IMXRT_LCD_BACKLIGHT=y +CONFIG_IMXRT_LCD_INPUT_BPP16=y +CONFIG_IMXRT_LCD_OUTPUT_16=y +CONFIG_IMXRT_LCD_BACKCOLOR=0x0 +CONFIG_IMXRT_LCD_HWIDTH=480 +CONFIG_IMXRT_LCD_HPULSE=41 +CONFIG_IMXRT_LCD_HFRONTPORCH=4 +CONFIG_IMXRT_LCD_HBACKPORCH=8 +CONFIG_IMXRT_LCD_VHEIGHT=272 +CONFIG_IMXRT_LCD_VPULSE=10 +CONFIG_IMXRT_LCD_VFRONTPORCH=4 +CONFIG_IMXRT_LCD_VBACKPORCH=2 +CONFIG_IMXRT_DATAEN_ACTIVE_HIGH=y +CONFIG_IMXRT_DATA_RISING_EDGE=y + +CONFIG_I2C=y +CONFIG_I2C_DRIVER=y +CONFIG_ARCH_HAVE_SPI_CS_CONTROL=y +CONFIG_SPI=y +CONFIG_SPI_EXCHANGE=y + +CONFIG_FB_MODULEINFO=y +CONFIG_DRIVERS_VIDEO=y +CONFIG_VIDEO_FB=y +CONFIG_INPUT=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_INPUT_GT9XX=y + +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_MAX_TASKS=128 +CONFIG_FS_PROCFS_EXCLUDE_ENVIRON=y + +CONFIG_EXAMPLES_FB=y +CONFIG_EXAMPLES_FB_DEFAULTFB="/dev/fb0" +CONFIG_EXAMPLES_FB_PROGNAME="fb" +CONFIG_EXAMPLES_FB_PRIORITY=100 +CONFIG_EXAMPLES_FB_STACKSIZE=2048 + +CONFIG_EXAMPLES_TOUCHSCREEN=y +CONFIG_EXAMPLES_TOUCHSCREEN_MINOR=0 +CONFIG_EXAMPLES_TOUCHSCREEN_DEVPATH="/dev/input0" +CONFIG_EXAMPLES_TOUCHSCREEN_NSAMPLES=0 + diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/Makefile b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/Makefile index 45b928370..528b9f1cc 100644 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/Makefile +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/Makefile @@ -82,6 +82,10 @@ ifeq ($(CONFIG_XIDATONG_SDIO_AUTOMOUNT),y) CSRCS += imxrt_mmcsd_automount.c endif +ifeq ($(CONFIG_INPUT_GT9XX),y) +CSRCS += imxrt_gt9xx.c +endif + ifeq ($(CONFIG_BSP_USING_CH438),y) CSRCS += imxrt_ch438.c ch438_demo.c endif diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/imxrt_bringup.c b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/imxrt_bringup.c index 7f6b1ee72..18922681b 100644 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/imxrt_bringup.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/imxrt_bringup.c @@ -51,6 +51,10 @@ # include "imxrt_ch438.h" #endif +#ifdef CONFIG_INPUT_GT9XX +#include "imxrt_gt9xx.h" +#endif + #include "xidatong.h" #include /* Must always be included last */ @@ -187,6 +191,19 @@ int imxrt_bringup(void) board_ch438_initialize(); #endif +#ifdef CONFIG_INPUT_GT9XX + /* Initialize the GT9XX touchscreen driver */ + + ret = imxrt_gt9xx_register(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: imxrt_ft5x06_register() failed: %d\n", ret); + } + + syslog(LOG_NOTICE, "Start initialize %d ok ...\n", ret); + +#endif + UNUSED(ret); return OK; } diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/imxrt_gt9xx.c b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/imxrt_gt9xx.c new file mode 100755 index 000000000..427f79a9c --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/imxrt_gt9xx.c @@ -0,0 +1,328 @@ +/**************************************************************************** + * boards/arm/imxrt/xidatong/src/imxrt_gt9xx.c + * + * Copyright 2019 ElFaro LAB S.L. All rights reserved. + * Author: Fabio Balzano + * + * Based on boards/arm/lpc54xx/lpcxpresso-lpc54628/src/lpc54_ft5x06.c + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file imxrt_gt9xx.c + * @brief gt9xx touch driver refer to imxrt_ft5x06.c + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2022.5.31 + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "imxrt_config.h" +#include "imxrt_gpio.h" +#include "imxrt_lpi2c.h" + +#include "arch/chip/irq.h" +#include "imxrt_iomuxc.h" + +#define gt_print printf + +#define GT9XX_I2C_ADDRESS 0x5D + +#define GPIO_GT9XX_INTR IMXRT_IRQ_GPIO2_30 + +#define IOMUX_GT9XX_RST (IOMUX_PULL_NONE | IOMUX_CMOS_OUTPUT | \ + IOMUX_DRIVE_40OHM | IOMUX_SPEED_MEDIUM | \ + IOMUX_SLEW_SLOW) + +#define GPIO_GT9XX_CTRSTN (GPIO_OUTPUT | GPIO_OUTPUT_ZERO | \ + GPIO_PORT2 | GPIO_PIN30 | IOMUX_GT9XX_RST) + +#define GPIO_GT9XX_CTINTN (GPIO_INTERRUPT | GPIO_INT_RISINGEDGE | \ + IOMUX_SW_DEFAULT | GPIO_PORT2 | GPIO_PIN30 ) + +#ifdef CONFIG_INPUT_GT9XX + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define GT9XX_FREQUENCY 400000 + +/**************************************************************************** + * Private Function Ptototypes + ****************************************************************************/ + +#ifndef CONFIG_GT9XX_POLLMODE +static int imxrt_gt9xx_attach(FAR const struct gt9xx_config_s *config, + xcpt_t isr, FAR void *arg); +static void imxrt_gt9xx_enable(FAR const struct gt9xx_config_s *config, + bool enable); +static void imxrt_gt9xx_clear(FAR const struct gt9xx_config_s *config); +#endif + +static void imxrt_gt9xx_wakeup(FAR const struct gt9xx_config_s *config); +static void imxrt_gt9xx_nreset(FAR const struct gt9xx_config_s *config, + bool state); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct gt9xx_config_s g_gt9xx_config = +{ + .address = GT9XX_I2C_ADDRESS, + .frequency = GT9XX_FREQUENCY, +#ifndef CONFIG_GT9XX_POLLMODE + .attach = imxrt_gt9xx_attach, + .enable = imxrt_gt9xx_enable, + .clear = imxrt_gt9xx_clear, +#endif + .wakeup = imxrt_gt9xx_wakeup, + .nreset = imxrt_gt9xx_nreset +}; + +#ifndef CONFIG_GT9XX_POLLMODE +static uint8_t g_gt9xx_irq; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imxrt_gt9xx_attach + * + * Description: + * Attach an GT9XX interrupt handler to a GPIO interrupt + * + ****************************************************************************/ + +#ifndef CONFIG_GT9XX_POLLMODE +static int imxrt_gt9xx_attach(FAR const struct gt9xx_config_s *config, + xcpt_t isr, FAR void *arg) +{ + return irq_attach(g_gt9xx_irq, isr, arg); +} +#endif + +/**************************************************************************** + * Name: imxrt_gt9xx_enable + * + * Description: + * Enable or disable a GPIO interrupt + * + ****************************************************************************/ + +#ifndef CONFIG_GT9XX_POLLMODE +static void imxrt_gt9xx_enable(FAR const struct gt9xx_config_s *config, + bool enable) +{ + if (enable) + { + up_enable_irq(g_gt9xx_irq); + } + else + { + up_disable_irq(g_gt9xx_irq); + } +} +#endif + +/**************************************************************************** + * Name: imxrt_gt9xx_clear + * + * Description: + * Acknowledge/clear any pending GPIO interrupt + * + ****************************************************************************/ + +#ifndef CONFIG_GT9XX_POLLMODE +static void imxrt_gt9xx_clear(FAR const struct gt9xx_config_s *config) +{ + imxrt_gpioirq_disable(g_gt9xx_irq); +} +#endif + +/**************************************************************************** + * Name: imxrt_gt9xx_wakeup + * + * Description: + * Issue WAKE interrupt to GT9XX to change the GT9XX from Hibernate to + * Active mode. + * + ****************************************************************************/ + +static void imxrt_gt9xx_wakeup(FAR const struct gt9xx_config_s *config) +{ + /* We do not have access to the WAKE pin in the implementation */ +} + +/**************************************************************************** + * Name: imxrt_gt9xx_nreset + * + * Description: + * Control the chip reset pin (active low) + * + ****************************************************************************/ + +static void imxrt_gt9xx_nreset(FAR const struct gt9xx_config_s *config, + bool nstate) +{ + imxrt_gpio_write(GPIO_GT9XX_CTRSTN, nstate); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#define IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_MASK (0x7U) +#define IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_SHIFT (0U) + +#define IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(x) (((uint32_t)(((uint32_t)(x)) << IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_SHIFT)) & IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_MASK) +#define IOMUXC_SW_MUX_CTL_PAD_SION_MASK (0x10U) +#define IOMUXC_SW_MUX_CTL_PAD_SION_SHIFT (4U) + +#define IOMUXC_SW_MUX_CTL_PAD_SION(x) (((uint32_t)(((uint32_t)(x)) << IOMUXC_SW_MUX_CTL_PAD_SION_SHIFT)) & IOMUXC_SW_MUX_CTL_PAD_SION_MASK) + +#define IOMUXC_GPIO_B1_14_GPIO2_IO30 0x401F81B4U, 0x5U, 0, 0, 0x401F83A4U + +static inline void IOMUXC_SetPinMux(uint32_t muxRegister, + uint32_t muxMode, + uint32_t inputRegister, + uint32_t inputDaisy, + uint32_t configRegister, + uint32_t inputOnfield) +{ + *((volatile uint32_t *)muxRegister) = + IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield); + + if (inputRegister) + { + *((volatile uint32_t *)inputRegister) = inputDaisy; + } +} + +static inline void IOMUXC_SetPinConfig(uint32_t muxRegister, + uint32_t muxMode, + uint32_t inputRegister, + uint32_t inputDaisy, + uint32_t configRegister, + uint32_t configValue) +{ + if (configRegister) + { + *((volatile uint32_t *)configRegister) = configValue; + } +} + +void imxrt_config_gt9xx_pins(void) +{ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_14_GPIO2_IO30, /* WAKEUP is configured as GPIO5_IO00 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_14_GPIO2_IO30, + 0x10B0u); +} + +/**************************************************************************** + * Name: imxrt_gt9xx_register + * + * Description: + * Register the GT9XX touch panel driver + * + ****************************************************************************/ + +int imxrt_gt9xx_register(void) +{ + FAR struct i2c_master_s *i2c; + int ret; + + /* Initialize CTRSTN pin */ + imxrt_config_gpio(GPIO_GT9XX_CTRSTN); + imxrt_gpio_write(GPIO_GT9XX_CTRSTN, false); + +#ifndef CONFIG_GT9XX_POLLMODE + int irq; + + /* Initialize GPIO interrupt pin. */ + imxrt_config_gpio(GPIO_GT9XX_CTINTN); + + irq = GPIO_GT9XX_INTR; + DEBUGASSERT(irq > 0 && irq < UINT8_MAX); + g_gt9xx_irq = (uint8_t)irq; + + /* Make sure that the interrupt is disabled at the NVIC */ + imxrt_gpioirq_disable(irq); + up_disable_irq(irq); +#endif + + /* Take the GT9XX out of reset */ + + /* The GT9XX is on LPI2C1. Get the handle and register the GT9XX device */ + + i2c = imxrt_i2cbus_initialize(1); + if (i2c == NULL) + { + syslog(LOG_ERR, "ERROR: Failed to get LPI2C1 interface\n"); + return -ENODEV; + } + else + { + ret = gt9xx_register(i2c, &g_gt9xx_config, 0); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register GT9XX driver: %d\n", ret); + imxrt_gpio_write(GPIO_GT9XX_CTRSTN, false); + imxrt_i2cbus_uninitialize(i2c); + return ret; + } + } + + return OK; +} + +#endif /* CONFIG_INPUT_GT9XX*/ diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/imxrt_gt9xx.h b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/imxrt_gt9xx.h new file mode 100755 index 000000000..073c044ba --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong/src/imxrt_gt9xx.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +/** + * @file imxrt_gt9xx.h + * @brief API for imxrt gt9xx. + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2022.5.31 + */ + +#ifndef __IMXRT_GT9XX_H_ +#define __IMXRT_GT9XX_H_ + +int imxrt_gt9xx_register(void); + +#endif /* __IMXRT_GT9XX_H__ */ + diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/build.sh b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/build.sh old mode 100644 new mode 100755 diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/drivers/input/Kconfig b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/drivers/input/Kconfig new file mode 100755 index 000000000..68504001c --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/drivers/input/Kconfig @@ -0,0 +1,570 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +menuconfig INPUT + bool "Input Device Support" + default n + ---help--- + This directory holds implementations of input device drivers. + This includes such things as touchscreen and keypad drivers. + See include/nuttx/input/*.h for registration information. + +if INPUT + +config INPUT_MOUSE + bool "Enable mouse support" + default n + ---help--- + Enable support for mouse devices. + +if INPUT_MOUSE + +config INPUT_MOUSE_WHEEL + bool "Enable mouse wheel support" + default n + ---help--- + Enable support for a 4-button mouse report that includes a while + position. + +endif # INPUT_MOUSE + +config INPUT_TOUCHSCREEN + bool + default n + +config INPUT_MAX11802 + bool "MAX11802 touchscreen controller" + default n + select SPI + select INPUT_TOUCHSCREEN + ---help--- + Enable support for the MAX11802 touchscreen controller + +config INPUT_TSC2007 + bool "TI TSC2007 touchscreen controller" + default n + select I2C + select INPUT_TOUCHSCREEN + ---help--- + Enable support for the TI TSC2007 touchscreen controller + +if INPUT_TSC2007 + +config TSC2007_8BIT + bool "TSC2007 8-bit Conversions" + default n + ---help--- + Use faster, but less accurate, 8-bit conversions. Default: 12-bit conversions. + +config TSC2007_MULTIPLE + bool "Multiple TSC2007 Devices" + default n + ---help--- + Can be defined to support multiple TSC2007 devices on board. + +config TSC2007_NPOLLWAITERS + int "Number TSC2007 poll waiters" + default 4 + ---help--- + Maximum number of threads that can be waiting on poll() + +endif # INPUT_TSC2007 + +config INPUT_FT5X06 + bool "FocalTech FT5x06 multi-touch, capacitive touch panel controller" + default n + select I2C + select INPUT_TOUCHSCREEN + ---help--- + Enable support for the FocalTech FT5x06 multi-touch, capacitive + touch panel controller + +config INPUT_GT9XX + bool "Goodix GT9XX touch panel controller" + default n + select I2C + select INPUT_TOUCHSCREEN + ---help--- + Enable support for the Goodix GT9XX multi-touch, capacitive + touch panel controller + +config INPUT_FT5336 + bool "FocalTech FT5336 multi-touch, capacitive touch panel controller" + default n + select I2C + select INPUT_FT5X06 + select INPUT_TOUCHSCREEN + depends on EXPERIMENTAL + ---help--- + Enable support for the FocalTech FT5x06 multi-touch, capacitive + touch panel controller + +if INPUT_FT5X06 + +config FT5X06_POLLMODE + bool "Polled mode" + default n + ---help--- + Run the FT5x06 in a non-interrupt driven polled mode. Events will + not be driven by interrupts but rather based on a timed poll. + + This is a non-optimal design both because (1) it will lead to delays + in detecting touch related events and (2) it will consume a + significant amount of CPU time to perform the polling. + +config FT5X06_SWAPXY + bool "Swap X/Y" + default n + ---help--- + Reverse the meaning of X and Y to handle different LCD orientations. + +config FT5X06_SINGLEPOINT + bool "Single point" + default n + ---help--- + Do no report multi-touch events + +if FT5X06_SINGLEPOINT + +config FT5X06_THRESHX + int "X threshold" + default 12 + ---help--- + New touch positions will only be reported when the X or Y data changes by these + thresholds. This trades reduced data rates for some loss in dragging accuracy. For + 12-bit values the raw ranges are 0-4095. So for example, if your display is + 320x240, then THRESHX=13 and THRESHY=17 would correspond to one pixel. Default: 12 + +config FT5X06_THRESHY + int "Y threshold" + default 12 + ---help--- + New touch positions will only be reported when the X or Y data changes by these + thresholds. This trades reduced data rates for some loss in dragging accuracy. For + 12-bit values the raw ranges are 0-4095. So for example, if your display is + 320x240, then THRESHX=13 and THRESHY=17 would correspond to one pixel. Default: 12 + +endif # FT5X06_SINGLEPOINT + +config FT5X06_NPOLLWAITERS + int "Number FT5336/FT5x06 poll waiters" + default 4 + ---help--- + Maximum number of threads that can be waiting on poll() + +endif # INPUT_FT5X06 + +config INPUT_ADS7843E + bool "TI ADS7843/TSC2046 touchscreen controller" + default n + select SPI + select INPUT_TOUCHSCREEN + ---help--- + Enable support for the TI/Burr-Brown ADS7842 touchscreen controller. I believe + that driver should be compatible with the TI/Burr-Brown TSC2046 and XPT2046 + touchscreen controllers as well. + +if INPUT_ADS7843E + +config ADS7843E_MULTIPLE + bool "Multiple ADS7843E Devices" + default n + ---help--- + Can be defined to support multiple ADS7843E devices on board. + +config ADS7843E_NPOLLWAITERS + int "Number poll waiters" + default 4 + ---help--- + Maximum number of threads that can be waiting on poll() + +config ADS7843E_SPIDEV + int "SPI bus number" + default 0 + ---help--- + Selects the SPI bus number identifying that SPI interface that + connects the ADS843E to the MCU. + +config ADS7843E_DEVMINOR + int "Input device minor number" + default 0 + ---help--- + The ADS7843E device will be registered as /dev/inputN where N is the + value provided by this setting. + +config ADS7843E_SPIMODE + int "SPI mode" + default 0 + range 0 3 + ---help--- + Controls the SPI mode. The device should work in mode 0, but + sometimes you need to experiment. + +config ADS7843E_FREQUENCY + int "SPI frequency" + default 100000 + ---help--- + Define to use a different SPI bus frequency. + +config ADS7843E_SWAPXY + bool "Swap X/Y" + default n + ---help--- + Reverse the meaning of X and Y to handle different LCD orientations. + +config ADS7843E_THRESHX + int "X threshold" + default 12 + ---help--- + New touch positions will only be reported when the X or Y data changes by these + thresholds. This trades reduced data rates for some loss in dragging accuracy. For + 12-bit values the raw ranges are 0-4095. So for example, if your display is + 320x240, then THRESHX=13 and THRESHY=17 would correspond to one pixel. Default: 12 + +config ADS7843E_THRESHY + int "Y threshold" + default 12 + ---help--- + New touch positions will only be reported when the X or Y data changes by these + thresholds. This trades reduced data rates for some loss in dragging accuracy. For + 12-bit values the raw ranges are 0-4095. So for example, if your display is + 320x240, then THRESHX=13 and THRESHY=17 would correspond to one pixel. Default: 12 + +endif # INPUT_ADS7843E + +config INPUT_MXT + bool "Atmel maXTouch Driver" + select INPUT_TOUCHSCREEN + default n + ---help--- + Enables support for the Atmel maXTouch driver + +if INPUT_MXT + +config MXT_THRESHX + int "X threshold" + default 5 + ---help--- + New touch positions will only be reported when the X or Y data + changes by these thresholds. This trades reduced data rates for some + loss in dragging accuracy. For 12-bit values the raw ranges are + 0-4095. So for example, if your display is 800x480, then THRESHX=5 + and THRESHY=8 would correspond to a one pixel change. Default: 5 + + NOTE: This does nothing to reduce the interrupt rate. It only + reduces the rate at which touch events are reports. + +config MXT_THRESHY + int "Y threshold" + default 8 + ---help--- + New touch positions will only be reported when the X or Y data + changes by these thresholds. This trades reduced data rates for some + loss in dragging accuracy. For 12-bit values the raw ranges are + 0-4095. So for example, if your display is 800x480, then THRESHX=5 + and THRESHY=8 would correspond to a one pixel change. Default: 8 + + NOTE: This does nothing to reduce the interrupt rate. It only + reduces the rate at which touch events are reports. + +config MXT_NPOLLWAITERS + int "Number poll waiters" + default 4 + ---help--- + Maximum number of threads that can be waiting on poll() + +config MXT_DISABLE_CONFIG_DEBUG_INFO + bool "Disable verbose debug output" + default y + depends on DEBUG_INPUT_INFO + ---help--- + The maXTouch tends to generate interrupts at a high rate during the + contact. If verbose debug is enabled in this driver, you may not + be able to get anything done because of the high debug output rate. + + This setting will allow you to keep verbose touchscreen debug output + in other modules, but to specifically suppress the debug out from + the MXT driver. Debug (non-verbose) errors will still be generated, + but the chit-chat level will be eliminated. + +endif # INPUT_MXT + +config INPUT_STMPE811 + bool "STMicro STMPE811 Driver" + default n + select INPUT_TOUCHSCREEN + ---help--- + Enables support for the STMPE811 driver + +if INPUT_STMPE811 + +choice + prompt "STMPE Interface" + default STMPE811_I2C + +config STMPE811_SPI + bool "SPI Interface" + select SPI + ---help--- + Enables support for the SPI interface (not currently supported) + +config STMPE811_I2C + bool "STMPE811 I2C Interface" + select I2C + ---help--- + Enables support for the I2C interface + +endchoice + +config STMPE811_ACTIVELOW + bool "Active Low Interrupt" + default n + ---help--- + The STMPE811 interrupt is provided by a discrete input (usually a + GPIO interrupt on most MCU architectures). This setting determines + whether the interrupt is active high (or rising edge triggered) or + active low (or falling edge triggered). Default: Active + high/rising edge. + +config STMPE811_EDGE + bool "Edge triggered Interrupt" + default n + ---help--- + The STMPE811 interrupt is provided by a discrete input (usually a + GPIO interrupt on most MCU architectures). This setting determines + whether the interrupt is edge or level triggered. Default: Level + triggered. + +config STMPE811_MULTIPLE + bool "Multiple STMPE811 Devices" + default n + ---help--- + Can be defined to support multiple STMPE811 devices on board. + +config STMPE811_NPOLLWAITERS + int "Number poll waiters" + default 4 + ---help--- + Maximum number of threads that can be waiting on poll() + +config STMPE811_TSC_DISABLE + bool "Disable STMPE811 Touchscreen Support" + default n + ---help--- + Disable driver touchscreen functionality. + +config STMPE811_SWAPXY + bool "Swap X/Y" + default n + depends on !STMPE811_TSC_DISABLE + ---help--- + Reverse the meaning of X and Y to handle different LCD orientations. + +config STMPE811_THRESHX + int "X threshold" + default 12 + depends on !STMPE811_TSC_DISABLE + ---help--- + STMPE811 touchscreen data comes in a a very high rate. New touch positions + will only be reported when the X or Y data changes by these thresholds. + This trades reduced data rates for some loss in dragging accuracy. The + STMPE811 is configure for 12-bit values the raw ranges are 0-4095. So + for example, if your display is 320x240, then THRESHX=13 and THRESHY=17 + would correspond to one pixel. Default: 12 + +config STMPE811_THRESHY + int "Y threshold" + default 12 + depends on !STMPE811_TSC_DISABLE + ---help--- + STMPE811 touchscreen data comes in a a very high rate. New touch positions + will only be reported when the X or Y data changes by these thresholds. + This trades reduced data rates for some loss in dragging accuracy. The + STMPE811 is configure for 12-bit values the raw ranges are 0-4095. So + for example, if your display is 320x240, then THRESHX=13 and THRESHY=17 + would correspond to one pixel. Default: 12 + +config STMPE811_ADC_DISABLE + bool "Disable STMPE811 ADC Support" + default y + ---help--- + Disable driver ADC functionality. + +config STMPE811_GPIO_DISABLE + bool "Disable STMPE811 GPIO Support" + default y + ---help--- + Disable driver GPIO functionality. + +config STMPE811_GPIOINT_DISABLE + bool "Disable STMPE811 GPIO Interrupt Support" + default y + depends on !STMPE811_GPIO_DISABLE + ---help--- + Disable driver GPIO interrupt functionality (ignored if GPIO functionality is + disabled). + +config STMPE811_TEMP_DISABLE + bool "Disable STMPE811 Temperature Sensor Support" + default y + ---help--- + Disable driver temperature sensor functionality. + +config STMPE811_REGDEBUG + bool "Enable Register-Level STMPE811 Debug" + default n + depends on DEBUG_FEATURES + ---help--- + Enable very low register-level debug output. + +endif # INPUT_STMPE811 + +config INPUT_CYPRESS_MBR3108 + bool "Enable Cypress MBR3108 CapSense driver" + default n + select INPUT_TOUCHSCREEN + ---help--- + Enable support for Cypress MBR3108 CapSense touch button & proximity + input sensor. + +if INPUT_CYPRESS_MBR3108 + +config INPUT_CYPRESS_MBR3108_DEBUG + bool "Enable debug support for Cypress sensor" + default n + depends on DEBUG_FEATURES + ---help--- + Enable debugging traces for MBR3108 driver + +config INPUT_CYPRESS_MBR3108_NPOLLWAITERS + int "Number of waiters to poll" + default 1 + ---help--- + Maximum number of threads that can be waiting on poll() + +endif # INPUT_CYPRESS_MBR3108 + +config INPUT_BUTTONS + bool "Button Inputs" + default n + ---help--- + Enable standard button upper half driver. + +if INPUT_BUTTONS + +config INPUT_BUTTONS_LOWER + bool "Generic Lower Half Button Driver" + default n + depends on ARCH_BUTTONS && ARCH_IRQBUTTONS + ---help--- + If the board supports the standard button interfaces as + defined in include/nuttx/board.h header file, then this + standard button lower half driver might be usable. + + In order for this generic driver to be usable: + + 1. The board implementation must provide the button + interfaces as defined in include/nuttx/board.h + 2. The board implementation must support interrupts for each + button. + + If your board does not meet these requirements, then the + button_lower.c file can still be copied to your your + board src/ directory and modified for your specific board + requirements. + +config INPUT_BUTTONS_NPOLLWAITERS + int "Max Number of Poll Waiters" + default 2 + +endif # INPUT_BUTTONS + +config INPUT_DJOYSTICK + bool "Discrete Joystick" + default n + ---help--- + Enable standard discrete joystick upper half driver. A discrete + joystick refers to a joystick that could be implemented entirely + with GPIO input pins. So up, down, left, and right are all discrete + values like buttons (as opposed to integer values like you might + obtain from an analog joystick). + +if INPUT_DJOYSTICK + +config INPUT_DJOYSTICK_NPOLLWAITERS + int "Max Number of Poll Waiters" + default 2 + +endif # INPUT_DJOYSTICK + +config INPUT_AJOYSTICK + bool "Analog Joystick" + default n + ---help--- + Enable standard analog joystick upper half driver. An analog + joystick refers to a joystick that provides position data as an + integer value that might have been obtained through Analog- + to-Digital Conversion (ADC). The analog positional data may also + be accompanied by discrete button data. + +if INPUT_AJOYSTICK + +config INPUT_AJOYSTICK_NPOLLWAITERS + int "Max Number of Poll Waiters" + default 2 + +endif # INPUT_AJOYSTICK + +config INPUT_NUNCHUCK + bool "Nintendo Wii Nunchuck Joystick (White Model)" + default n + select I2C + ---help--- + Enable a Nintendo Wii Nunchuck joystick upper half driver. The + nunchuck joystick provides position data as an integer value.The + analog positional data may also be accompanied by discrete + button data. + +if INPUT_NUNCHUCK + +config NUNCHUCK_NPOLLWAITERS + int "Max Number of Poll Waiters" + default 2 + +endif # INPUT_NUNCHUCK + +config INPUT_SPQ10KBD + bool "Solder Party Q10 BlackBerry Keyboard" + default n + select I2C + ---help--- + Enable the Solder Party Q10 BlackBerry Keyboard support. This + exposes itself as a standard keyboard at /dev/kbdN. + This keyboard exists both as a standalone module and integrated + into the Solder Party Keyboard FeatherWing. Information on this + can be found at https://www.solder.party/docs/keyboard-pmod/ + +if INPUT_SPQ10KBD + +config SPQ10KBD_DJOY + bool "Joystick Interface for Buttons" + select INPUT_DJOYSTICK + default n + +config SPQ10KBD_REGDBG + bool "Keyboard Register Debug" + default n + +config SPQ10KBD_BUFSIZE + int "Keyboard Buffer Size" + default 10 + +config SPQ10KBD_NPOLLWAITERS + int "Max Number of Poll Waiters" + default 2 + +endif # INPUT_SPQ10KBD + +endif # INPUT diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/drivers/input/Make.defs b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/drivers/input/Make.defs new file mode 100755 index 000000000..605f6ae3b --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/drivers/input/Make.defs @@ -0,0 +1,100 @@ +############################################################################ +# drivers/input/Make.defs +# +# 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. +# +############################################################################ + +# Don't build anything if there is no support for input devices + +ifeq ($(CONFIG_INPUT),y) + +# Include the selected touchscreen drivers + +ifeq ($(CONFIG_INPUT_TSC2007),y) + CSRCS += tsc2007.c +endif + +ifeq ($(CONFIG_INPUT_FT5X06),y) + CSRCS += ft5x06.c +endif + +ifeq ($(CONFIG_INPUT_GT9XX),y) + CSRCS += gt9xx.c +endif + +ifeq ($(CONFIG_INPUT_ADS7843E),y) + CSRCS += ads7843e.c +endif + +ifeq ($(CONFIG_INPUT_MAX11802),y) + CSRCS += max11802.c +endif + +ifeq ($(CONFIG_INPUT_MXT),y) + CSRCS += mxt.c +endif + +ifeq ($(CONFIG_INPUT_STMPE811),y) + CSRCS += stmpe811_base.c +ifneq ($(CONFIG_INPUT_STMPE811_TSC_DISABLE),y) + CSRCS += stmpe811_tsc.c +endif +ifneq ($(CONFIG_INPUT_STMPE811_GPIO_DISABLE),y) + CSRCS += stmpe811_gpio.c +endif +ifneq ($(CONFIG_INPUT_STMPE811_ADC_DISABLE),y) + CSRCS += stmpe811_adc.c +endif +ifneq ($(CONFIG_INPUT_STMPE811_TEMP_DISABLE),y) + CSRCS += stmpe811_temp.c +endif +endif + +ifeq ($(CONFIG_INPUT_CYPRESS_MBR3108),y) + CSRCS += cypress_mbr3108.c +endif + +ifeq ($(CONFIG_INPUT_BUTTONS),y) + CSRCS += button_upper.c +ifeq ($(CONFIG_INPUT_BUTTONS_LOWER),y) + CSRCS += button_lower.c +endif + +endif + +ifeq ($(CONFIG_INPUT_DJOYSTICK),y) + CSRCS += djoystick.c +endif + +ifeq ($(CONFIG_INPUT_AJOYSTICK),y) + CSRCS += ajoystick.c +endif + +ifeq ($(CONFIG_INPUT_NUNCHUCK),y) + CSRCS += nunchuck.c +endif + +ifeq ($(CONFIG_INPUT_SPQ10KBD),y) + CSRCS += spq10kbd.c +endif + +# Include input device driver build support + +DEPPATH += --dep-path input +VPATH += :input +CFLAGS += ${shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)input} +endif diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/drivers/input/gt9xx.c b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/drivers/input/gt9xx.c new file mode 100755 index 000000000..77496d9cf --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/drivers/input/gt9xx.c @@ -0,0 +1,1417 @@ +/**************************************************************************** + * drivers/input/gt9xx.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. + * + ****************************************************************************/ + +/* References: + * Dec. 18, 2012 + */ + +/* The FT5x06 Series ICs are single-chip capacitive touch panel controller + * ICs with a built-in 8 bit Micro-controller unit (MCU). They adopt the + * mutual capacitance approach, which supports true multi-touch capability. + * In conjunction with a mutual capacitive touch panel, the FT5x06 have + * user-friendly input functions, which can be applied on many portable + * devices, such as cellular phones, MIDs, netbook and notebook personal + * computers. + */ + +/** + * @file gt9xx.c + * @brief refer to imxrt_gt9xx.c codes. + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2022.5.31 + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Driver support ***********************************************************/ + +/* This format is used to construct the /dev/input[n] device driver path. It + * defined here so that it will be used consistently in all places. + */ + +#define DEV_FORMAT "/dev/input%d" +#define DEV_NAMELEN 16 + +#define GT9XX_VER_LEN 8 +#define GT9XX_INF_LEN 6 +#define GT9XX_CFG_LEN 3 + +/* In polled mode, the polling rate will decrease when there is no touch + * activity. These definitions represent the maximum and the minimum + * polling rates. + */ + +#define POLL_MINDELAY MSEC2TICK(50) +#define POLL_MAXDELAY MSEC2TICK(200) +#define POLL_INCREMENT MSEC2TICK(10) + +#define gt_print printf + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes the state of one GT9xx driver instance */ + +struct gt9xx_dev_s +{ + uint8_t crefs; /* Number of times the device + * has been opened */ + uint8_t nwaiters; /* Number of threads waiting for + * GT9xx data */ + volatile bool valid; /* True: New, valid touch data + * in touchbuf[] */ +#ifdef CONFIG_GT9XX_SINGLEPOINT + uint8_t lastid; /* Last reported touch id */ + uint8_t lastevent; /* Last reported event */ + int16_t lastx; /* Last reported X position */ + int16_t lasty; /* Last reported Y position */ +#endif + sem_t devsem; /* Manages exclusive access to + * this structure */ + sem_t waitsem; /* Used to wait for the + * availability of data */ + uint32_t frequency; /* Current I2C frequency */ +#ifdef CONFIG_GT9XX_POLLMODE + uint32_t delay; /* Current poll delay */ +#endif + + FAR const struct gt9xx_config_s *config; /* Board configuration data */ + FAR struct i2c_master_s *i2c; /* Saved I2C driver instance */ + struct work_s work; /* Supports the interrupt + * handling "bottom half" */ +#ifdef CONFIG_GT9XX_POLLMODE + struct wdog_s polltimer; /* Poll timer */ +#endif + uint8_t touchbuf[GT9XX_TOUCH_DATA_LEN]; /* Raw touch data */ + + /* The following is a list if poll structures of threads waiting for + * driver events. The 'struct pollfd' reference for each open is also + * retained in the f_priv field of the 'struct file'. + */ + + struct pollfd *fds[CONFIG_GT9XX_NPOLLWAITERS]; +}; + +// support 480 * 272 +uint8_t gt9xx_cfg_data[] = { + 0x5B, 0xE0, 0x01, 0x10, 0x01, 0x0A, 0x0D, 0x00, 0x01, 0x0A, + 0x28, 0x0F, 0x5A, 0x3C, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x28, 0x09, + 0x32, 0x34, 0x0C, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x1D, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x55, 0x94, 0xC5, 0x02, 0x07, 0x00, 0x00, 0x04, + 0x8D, 0x2B, 0x00, 0x80, 0x32, 0x00, 0x75, 0x3A, 0x00, 0x6C, + 0x43, 0x00, 0x64, 0x4F, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, + 0xF0, 0x4A, 0x3A, 0xFF, 0xFF, 0x27, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, + 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x26, 0x24, 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, + 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x81, 0x01 +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void gt9xx_notify(FAR struct gt9xx_dev_s *priv); +static void gt9xx_data_worker(FAR void *arg); +#ifdef CONFIG_GT9XX_POLLMODE +static void gt9xx_poll_timeout(wdparm_t arg); +#else +static int gt9xx_data_interrupt(int irq, FAR void *context, FAR void *arg); +#endif +static ssize_t gt9xx_sample(FAR struct gt9xx_dev_s *priv, FAR char *buffer, + size_t len); +static ssize_t gt9xx_waitsample(FAR struct gt9xx_dev_s *priv, + FAR char *buffer, size_t len); +static int gt9xx_bringup(FAR struct gt9xx_dev_s *priv); +static void gt9xx_shutdown(FAR struct gt9xx_dev_s *priv); + +/* Character driver methods */ + +static int gt9xx_open(FAR struct file *filep); +static int gt9xx_close(FAR struct file *filep); +static ssize_t gt9xx_read(FAR struct file *filep, FAR char *buffer, + size_t len); +static int gt9xx_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); +static int gt9xx_poll(FAR struct file *filep, struct pollfd *fds, + bool setup); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This the vtable that supports the character driver interface */ + +static const struct file_operations gt9xx_fops = +{ + gt9xx_open, /* open */ + gt9xx_close, /* close */ + gt9xx_read, /* read */ + NULL, /* write */ + NULL, /* seek */ + gt9xx_ioctl, /* ioctl */ + gt9xx_poll /* poll */ +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL /* unlink */ +#endif +}; + +/* Maps GT9xx touch events into bit encoded representation used by NuttX */ + +static const uint8_t g_event_map[4] = +{ + (TOUCH_DOWN | TOUCH_ID_VALID | TOUCH_POS_VALID), /* GT9XX_DOWN */ + (TOUCH_UP | TOUCH_ID_VALID), /* GT9XX_UP */ + (TOUCH_MOVE | TOUCH_ID_VALID | TOUCH_POS_VALID), /* GT9XX_CONTACT */ + TOUCH_ID_VALID /* GT9XX_INVALID */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int gt9xx_write_reg(FAR struct gt9xx_dev_s *priv, uint8_t *reg_val, uint16_t len) +{ + FAR const struct gt9xx_config_s *config; + struct i2c_msg_s msg[2]; + int ret; + int retries = 0; + + config = priv->config; + DEBUGASSERT(config != NULL); + + msg[0].frequency = priv->frequency; + msg[0].addr = config->address; + msg[0].flags = 0; + msg[0].buffer = reg_val; + msg[0].length = len; + + while(retries < 5) + { + ret = I2C_TRANSFER(priv->i2c, msg, 1); + if(ret == 2) break; + retries ++; + } + if (ret < 0) + { + ierr("gt: [%s] failed freq %ld addr %x ret %d\n", __func__, priv->frequency, config->address, ret); + return ret; + } + return ret; +} + +static int gt9xx_read_reg(FAR struct gt9xx_dev_s *priv, uint8_t *reg_addr, uint8_t *reg_val, uint16_t len) +{ + FAR const struct gt9xx_config_s *config; + struct i2c_msg_s msg[2]; + int ret; + int retries = 0; + + config = priv->config; + DEBUGASSERT(config != NULL); + + msg[0].frequency = priv->frequency; + msg[0].addr = config->address; + msg[0].flags = 0; + msg[0].buffer = reg_addr; + msg[0].length = GT9XX_ADDR_LENGTH; + + msg[1].frequency = priv->frequency; + msg[1].addr = config->address; + msg[1].flags = I2C_M_READ; + msg[1].buffer = reg_val; + msg[1].length = len - GT9XX_ADDR_LENGTH; + while(retries < 5) + { + ret = I2C_TRANSFER(priv->i2c, msg, 2); + if(ret == 2) break; + retries ++; + } + if (ret < 0) + { + ierr("gt: [%s] failed freq %ld addr %x ret %d\n", __func__, priv->frequency, config->address, ret); + return ret; + } + return ret; +} + +/**************************************************************************** + * Name: gt9xx_write_config + ****************************************************************************/ + +static int gt9xx_write_config(FAR struct gt9xx_dev_s *priv) +{ + int i, ret = -1; + uint8_t check_sum = 0; + uint8_t offet = 0x80FE - 0x8047 + 1 ; + + const uint8_t* cfg_info = gt9xx_cfg_data; + uint8_t cfg_info_len = sizeof(gt9xx_cfg_data) / sizeof(gt9xx_cfg_data[0]); + + uint8_t reg_data[GT9XX_CONFIG_MAX_LENGTH + GT9XX_ADDR_LENGTH] + = {GT9XX_REG_CONFIG_DATA >> 8, GT9XX_REG_CONFIG_DATA & 0xff}; + + memset(®_data[GT9XX_ADDR_LENGTH], 0, GT9XX_CONFIG_MAX_LENGTH); + memcpy(®_data[GT9XX_ADDR_LENGTH], cfg_info, cfg_info_len); + + check_sum = 0; + + for (i = GT9XX_ADDR_LENGTH; i < offet + GT9XX_ADDR_LENGTH; i++) + { + check_sum += reg_data[i]; + } + + reg_data[offet + GT9XX_ADDR_LENGTH] = (~check_sum) + 1; //checksum + reg_data[offet + GT9XX_ADDR_LENGTH + 1] = 1; //refresh + + gt_print("Driver send config."); + + ret = gt9xx_write_reg(priv, reg_data, offet + GT9XX_ADDR_LENGTH + 2); + + return ret; +} + + +/**************************************************************************** + * Name: gt9xx_notify + ****************************************************************************/ + +static void gt9xx_notify(FAR struct gt9xx_dev_s *priv) +{ + int i; + + /* If there are threads waiting on poll() for GT9xx data to become + * available, then wake them up now. NOTE: we wake up all waiting threads + * because we do not know that they are going to do. If they all try to + * read the data, then some make end up blocking after all. + */ + + for (i = 0; i < CONFIG_GT9XX_NPOLLWAITERS; i++) + { + struct pollfd *fds = priv->fds[i]; + if (fds) + { + fds->revents |= POLLIN; + iinfo("Report events: %02x\n", fds->revents); + nxsem_post(fds->sem); + } + } + + /* If there are threads waiting for read data, then signal one of them + * that the read data is available. + */ + + if (priv->nwaiters > 0) + { + /* After posting this semaphore, we need to exit because the GT9xx + * is no longer available. + */ + + nxsem_post(&priv->waitsem); + } +} + +/**************************************************************************** + * Name: gt9xx_data_worker + ****************************************************************************/ + +static void gt9xx_data_worker(FAR void *arg) +{ + FAR struct gt9xx_dev_s *priv = (FAR struct gt9xx_dev_s *)arg; + FAR const struct gt9xx_config_s *config; + FAR struct gt9xx_touch_data_s *sample; + uint8_t regaddr[3]; + int ret; + + /* Get a pointer the callbacks for convenience */ + + DEBUGASSERT(priv != NULL && priv->config != NULL); + config = priv->config; + + /* We need to have exclusive access to the touchbuf so that we do not + * corrupt any read operation that is in place. + */ + do + { + ret = nxsem_wait_uninterruptible(&priv->devsem); + + /* This would only fail if something canceled the worker thread? + * That is not expected. + */ + + DEBUGASSERT(ret == OK || ret == -ECANCELED); + } + while (ret < 0); + + /* Read touch data */ + + /* Set up the address write operation */ + + regaddr[0] = GT9XX_REG_READ_COOR >> 8; + regaddr[1] = GT9XX_REG_READ_COOR & 0xFF; + + ret = gt9xx_read_reg(priv, regaddr, priv->touchbuf, GT9XX_TOUCH_DATA_LEN); + + if (ret >= 0) + { + /* In polled mode, we may read invalid touch data. If there is + * no touch data, the GT9xx returns all 0xff the very first time. + * After that, it returns the same old stale data when there is + * no touch data. + */ + + if(priv->touchbuf[0] & 0xf) + { + gt_print("gt: [%s] get i2c %x reg %x %x ret %d\n", __func__, config->address, regaddr[0], regaddr[1], ret); + for(int i = 0; i < 10; i ++) + { + gt_print("%x ", priv->touchbuf[i]); + } + gt_print("\n"); + } + + sample = (FAR struct gt9xx_touch_data_s *)priv->touchbuf; + + /* Notify waiters (only if we ready some valid data). + * + * REVISIT: For improved performance consider moving the duplicate + * report and thresholding logic from gt9xx_sample() to here. That + * would save a context switch. + */ + sample->tdstatus &= 0xf; + + if (sample->tdstatus <= GT9XX_MAX_TOUCHES) + { + /* Notify any waiters that new GT9xx data is available */ + + priv->valid = true; + gt9xx_notify(priv); + } + +#ifdef CONFIG_GT9XX_POLLMODE + /* Update the poll rate */ + + if (sample->tdstatus > 0 && sample->tdstatus <= GT9XX_MAX_TOUCHES) + { + /* Keep it at the minimum if touches are detected. */ + + priv->delay = POLL_MINDELAY; + } + else if (priv->delay < POLL_MAXDELAY) + { + /* Otherwise, let the poll rate rise gradually up to the maximum + * if there is no touch. + */ + + priv->delay += POLL_INCREMENT; + } +#endif + } + + /* cmd end */ + gt9xx_write_reg(priv, regaddr, 3); + +#ifdef CONFIG_GT9XX_POLLMODE + /* Exit, re-starting the poll. */ + + wd_start(&priv->polltimer, priv->delay, + gt9xx_poll_timeout, (wdparm_t)priv); + +#else + /* Exit, re-enabling GT9xx interrupts */ + config->enable(config, true); +#endif + + nxsem_post(&priv->devsem); +} + +/**************************************************************************** + * Name: gt9xx_poll_timeout + ****************************************************************************/ + +#ifdef CONFIG_GT9XX_POLLMODE +static void gt9xx_poll_timeout(wdparm_t arg) +{ + FAR struct gt9xx_dev_s *priv = (FAR struct gt9xx_dev_s *)arg; + int ret; + + /* Transfer processing to the worker thread. Since GT9xx poll timer is + * disabled while the work is pending, no special action should be + * required to protected the work queue. + */ + + DEBUGASSERT(priv->work.worker == NULL); + ret = work_queue(HPWORK, &priv->work, gt9xx_data_worker, priv, 0); + if (ret != 0) + { + ierr("ERROR: Failed to queue work: %d\n", ret); + } +} +#endif + +/**************************************************************************** + * Name: gt9xx_data_interrupt + ****************************************************************************/ + +#ifndef CONFIG_GT9XX_POLLMODE +static int gt9xx_data_interrupt(int irq, FAR void *context, FAR void *arg) +{ + FAR struct gt9xx_dev_s *priv = (FAR struct gt9xx_dev_s *)arg; + FAR const struct gt9xx_config_s *config; + int ret; + + /* Get a pointer the callbacks for convenience (and so the code is not so + * ugly). + */ + + config = priv->config; + DEBUGASSERT(config != NULL); + + /* Disable further interrupts */ + + config->enable(config, false); + + /* Transfer processing to the worker thread. Since GT9xx interrupts are + * disabled while the work is pending, no special action should be required + * to protected the work queue. + */ + + DEBUGASSERT(priv->work.worker == NULL); + ret = work_queue(HPWORK, &priv->work, gt9xx_data_worker, priv, 0); + if (ret != 0) + { + ierr("ERROR: Failed to queue work: %d\n", ret); + } + + /* Clear any pending interrupts and return success */ + + config->clear(config); + return OK; +} +#endif + +/**************************************************************************** + * Name: gt9xx_sample + ****************************************************************************/ + +#ifdef CONFIG_GT9XX_SINGLEPOINT +static ssize_t gt9xx_sample(FAR struct gt9xx_dev_s *priv, FAR char *buffer, + size_t len) +{ + FAR struct gt9xx_touch_data_s *raw; + FAR struct gt9xx_touch_point_s *touch; + FAR struct touch_sample_s *sample; + FAR struct touch_point_s *point; + int16_t x; + int16_t y; + uint8_t event; + uint8_t id; + uint8_t finger; + + if (!priv->valid) + { + return 0; /* Nothing to read */ + } + + /* Raw data pointers (source) */ + + raw = (FAR struct gt9xx_touch_data_s *)priv->touchbuf; + touch = raw->touch; + + finger = priv->touchbuf[0]; + + if(finger == 0x0) + { + goto reset_and_drop; + } + + if((finger & 0x80) == 0) + { + goto reset_and_drop; + } + + if((finger & 0xf) == 0) + { + goto reset_and_drop; + } + + /* Get the reported X and Y positions */ +#ifdef CONFIG_GT9XX_SWAPXY + y = TOUCH_POINT_GET_X(touch[0]); + x = TOUCH_POINT_GET_Y(touch[0]); +#else + x = TOUCH_POINT_GET_X(touch[0]); + y = TOUCH_POINT_GET_Y(touch[0]); +#endif + + /* Get the touch point ID and event */ + + event = GT9XX_DOWN; + id = TOUCH_POINT_GET_ID(touch[0]); + + if (event == GT9XX_INVALID) + { + priv->lastevent = GT9XX_INVALID; + goto reset_and_drop; + } + + gt_print("gt: [%s] event %d id %d\n", __func__, event, id); + + if (id == priv->lastid && event == priv->lastevent) + { + /* Same ID and event.. Is there positional data? */ + + if (raw->tdstatus == 0 || event == GT9XX_UP) + { + /* No... no new touch data */ + + goto reset_and_drop; + } + else + { + int16_t deltax; + int16_t deltay; + + /* Compare the change in position from the last report. */ + + deltax = (x - priv->lastx); + if (deltax < 0) + { + deltax = -deltax; + } + + if (deltax < CONFIG_GT9XX_THRESHX) + { + /* There as been no significant change in X, try Y */ + + deltay = (y - priv->lasty); + if (deltay < 0) + { + deltay = -deltay; + } + + if (deltax < CONFIG_GT9XX_THRESHX) + { + /* Ignore... no significant change in Y either */ + + goto drop; + } + } + } + } + + priv->lastid = id; + priv->lastevent = event; + priv->lastx = x; + priv->lasty = y; + + /* User data buffer points (sink) */ + + /* Return the number of touches read */ + + sample = (FAR struct touch_sample_s *)buffer; + sample->npoints = 1; + + /* Decode and return the single touch point */ + + point = sample->point; + point[0].id = id; + point[0].flags = g_event_map[event]; + point[0].x = x; + point[0].y = y; + point[0].h = 0; + point[0].w = 0; + point[0].pressure = 0; + + priv->valid = false; + return SIZEOF_TOUCH_SAMPLE_S(1); + +reset_and_drop: + priv->lastx = 0; + priv->lasty = 0; +drop: + priv->valid = false; + return 0; /* No new touches read. */ +} +#else +static ssize_t gt9xx_sample(FAR struct gt9xx_dev_s *priv, FAR char *buffer, + size_t len) +{ + FAR struct gt9xx_touch_data_s *raw; + FAR struct gt9xx_touch_point_s *touch; + FAR struct touch_sample_s *sample; + FAR struct touch_point_s *point; + unsigned int maxtouches; + unsigned int ntouches; + int i; + + maxtouches = (len - sizeof(int)) / sizeof(struct touch_point_s); + DEBUGASSERT(maxtouches > 0); /* Already verified */ + + if (!priv->valid) + { + return 0; /* Nothing to read */ + } + + /* Raw data pointers (source) */ + + raw = (FAR struct gt9xx_touch_data_s *)priv->touchbuf; + touch = raw->touch; + + /* Decode number of touches */ + + ntouches = raw->tdstatus; + DEBUGASSERT(ntouches <= GT9XX_MAX_TOUCHES); + + if (ntouches > maxtouches) + { + ntouches = maxtouches; + } + + if (ntouches < 1) + { + priv->valid = false; + return 0; /* No touches read. */ + } + + /* User data buffer points (sink) */ + + sample = (FAR struct touch_sample_s *)buffer; + point = sample->point; + + /* Return the number of touches read */ + + sample->npoints = ntouches; + + /* Decode and return the touch points */ + + for (i = 0; i < ntouches; i++) + { + int event = TOUCH_POINT_GET_EVENT(touch[i]); + + point[i].id = TOUCH_POINT_GET_ID(touch[i]); + point[i].flags = g_event_map[event]; +#ifdef CONFIG_GT9XX_SWAPXY + point[i].y = TOUCH_POINT_GET_X(touch[i]); + point[i].x = TOUCH_POINT_GET_Y(touch[i]); +#else + point[i].x = TOUCH_POINT_GET_X(touch[i]); + point[i].y = TOUCH_POINT_GET_Y(touch[i]); +#endif + point[i].h = 0; + point[i].w = 0; + point[i].pressure = 0; + +// gt_print("gt: [%s] %d - touch %x %x %x %x id %d flags %x x %d y %d\n", __func__, +// i, +// touch[i].xl, touch[i].xh, touch[i].yl, touch[i].yh, +// point[i].id, point[i].flags, +// point[i].x, point[i].y); + + } + + priv->valid = false; + return SIZEOF_TOUCH_SAMPLE_S(ntouches); +} +#endif /* CONFIG_GT9XX_SINGLEPOINT */ + +/**************************************************************************** + * Name: gt9xx_waitsample + ****************************************************************************/ + +static ssize_t gt9xx_waitsample(FAR struct gt9xx_dev_s *priv, + FAR char *buffer, size_t len) +{ + int ret; + + /* Disable pre-emption to prevent other threads from getting control while + * we muck with the semaphores. + */ + + sched_lock(); + + /* Now release the semaphore that manages mutually exclusive access to + * the device structure. This may cause other tasks to become ready to + * run, but they cannot run yet because pre-emption is disabled. + */ + + nxsem_post(&priv->devsem); + + /* Try to get the a sample... if we cannot, then wait on the semaphore + * that is posted when new sample data is available. + */ + + while (!priv->valid) + { + /* Increment the count of waiters */ + + priv->nwaiters++; + + /* Wait for a change in the GT9xx state */ + + ret = nxsem_wait(&priv->waitsem); + priv->nwaiters--; + + if (ret < 0) + { + ierr("ERROR: nxsem_wait failed: %d\n", ret); + goto errout; + } + } + + /* Re-acquire the semaphore that manages mutually exclusive access to + * the device structure. We may have to wait here. But we have our + * sample. Interrupts and pre-emption will be re-enabled while we wait. + */ + + ret = nxsem_wait(&priv->devsem); + if (ret >= 0) + { + /* Now sample the data. + * + * REVISIT: Is it safe to assume that priv->valid will always be + * true? I think that sched_lock() would protect the setting. + */ + + ret = gt9xx_sample(priv, buffer, len); + } + +errout: + /* Restore pre-emption. We might get suspended here but that is okay + * because we already have our sample. Note: this means that if there + * were two threads reading from the GT9xx for some reason, the data + * might be read out of order. + */ + + sched_unlock(); + return ret; +} + +int gt9xx_get_version(FAR struct gt9xx_dev_s *priv) +{ + FAR const struct gt9xx_config_s *config; + int ret; + uint8_t reg_addr[2]; + uint8_t reg_val[GT9XX_VER_LEN] = {0}; + + config = priv->config; + DEBUGASSERT(config != NULL); + + reg_addr[0] = (GT9XX_REG_VERSION) >> 8; /* config address */ + reg_addr[1] = (GT9XX_REG_VERSION) & 0xFF; + + ret = gt9xx_read_reg(priv, reg_addr, reg_val, GT9XX_VER_LEN); + + if (ret < 0) + { + ierr("gt: [%s] failed freq %ld addr %x ret %d\n", __func__, priv->frequency, config->address, ret); + return ret; + } + + gt_print("IC version: %s_%x%x\n", reg_val, reg_val[4], reg_val[5]); + + return OK; +} + +int gt9xx_get_info(FAR struct gt9xx_dev_s *priv) +{ + FAR const struct gt9xx_config_s *config; + int ret; + uint8_t reg_addr[2]; + uint8_t reg_val[GT9XX_INF_LEN] = {0}; + uint16_t abs_x_max = GT9XX_MAX_WIDTH; + uint16_t abs_y_max = GT9XX_MAX_HEIGHT; + uint8_t int_trigger_type = GT9XX_INT_TRIGGER; + + config = priv->config; + DEBUGASSERT(config != NULL); + + reg_addr[0] = (GT9XX_REG_CONFIG_DATA + 1) >> 8; /* config address */ + reg_addr[1] = (GT9XX_REG_CONFIG_DATA + 1) & 0xFF; + + ret = gt9xx_read_reg(priv, reg_addr, reg_val, GT9XX_INF_LEN); + + if (ret < 0) + { + ierr("gt: [%s] failed freq %ld addr %x ret %d\n", __func__, priv->frequency, config->address, ret); + return ret; + } + + abs_x_max = (reg_val[1] << 8) + reg_val[0]; + abs_y_max = (reg_val[3] << 8) + reg_val[2]; + + reg_addr[0] = (GT9XX_REG_CONFIG_DATA + 6) >> 8; /* config address */ + reg_addr[1] = (GT9XX_REG_CONFIG_DATA + 6) & 0xFF; + + ret = gt9xx_read_reg(priv, reg_addr, reg_val, GT9XX_CFG_LEN); + + if (ret < 0) + { + ierr("gt: [%s] failed freq %ld addr %x ret %d\n", __func__, priv->frequency, config->address, ret); + return ret; + } + + int_trigger_type = reg_val[0] & 0x03; + + iinfo("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x\n", + abs_x_max, abs_y_max, int_trigger_type); + + return OK; +} + + +/**************************************************************************** + * Name: gt9xx_bringup + ****************************************************************************/ + +static int gt9xx_bringup(FAR struct gt9xx_dev_s *priv) +{ + FAR const struct gt9xx_config_s *config; + config = priv->config; + DEBUGASSERT(config != NULL); + +#ifndef CONFIG_GT9XX_POLLMODE + /* Enable GT9xx interrupts */ + config->clear(config); + config->enable(config, true); +#endif + gt9xx_get_version(priv); + gt9xx_get_info(priv); + return OK; +} + +/**************************************************************************** + * Name: gt9xx_shutdown + ****************************************************************************/ + +static void gt9xx_shutdown(FAR struct gt9xx_dev_s *priv) +{ +#ifdef CONFIG_GT9XX_POLLMODE + /* Stop the poll timer */ + + wd_cancel(&priv->polltimer); + +#else + FAR const struct gt9xx_config_s *config = priv->config; + + /* Make sure that the GT9xx interrupt is disabled */ + + config->clear(config); + config->enable(config, false); +#endif +} + +/**************************************************************************** + * Name: gt9xx_open + ****************************************************************************/ + +static int gt9xx_open(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct gt9xx_dev_s *priv; + uint8_t tmp; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct gt9xx_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + ierr("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + /* Increment the reference count */ + + tmp = priv->crefs + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + goto errout_with_sem; + } + + /* When the reference increments to 1, this is the first open event + * on the driver.. and the time when we must initialize the driver. + */ + + if (tmp == 1) + { + ret = gt9xx_bringup(priv); + if (ret < 0) + { + ierr("ERROR: gt9xx_bringup failed: %d\n", ret); + goto errout_with_sem; + } + + ret = gt9xx_write_config(priv); + if (ret < 0) + { + ierr("ERROR: gt9xx_write_config failed: %d\n", ret); + goto errout_with_sem; + } + } + + /* Save the new open count on success */ + + priv->crefs = tmp; + +errout_with_sem: + nxsem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Name: gt9xx_close + ****************************************************************************/ + +static int gt9xx_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct gt9xx_dev_s *priv; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct gt9xx_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + ierr("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + /* Decrement the reference count unless it would decrement a negative + * value. + */ + + if (priv->crefs >= 1) + { + priv->crefs--; + } + + /* When the count decrements to zero, there are no further open references + * to the driver and it can be uninitialized. + */ + + if (priv->crefs == 0) + { + gt9xx_shutdown(priv); + } + + nxsem_post(&priv->devsem); + return OK; +} + +/**************************************************************************** + * Name: gt9xx_read + ****************************************************************************/ + +static ssize_t gt9xx_read(FAR struct file *filep, FAR char *buffer, + size_t len) +{ + FAR struct inode *inode; + FAR struct gt9xx_dev_s *priv; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct gt9xx_dev_s *)inode->i_private; + + /* Verify that the caller has provided a buffer large enough to receive + * the touch data. + */ + + if (len < SIZEOF_TOUCH_SAMPLE_S(1)) + { + /* We could provide logic to break up a touch report into segments and + * handle smaller reads... but why? + */ + + return -ENOSYS; + } + + /* Get exclusive access to the driver data structure */ + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + ierr("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + /* Try to read sample data. */ + + ret = gt9xx_sample(priv, buffer, len); + while (ret == 0) + { + /* Sample data is not available now. We would have to wait to receive + * sample data. If the user has specified the O_NONBLOCK option, then + * just return an error. + */ + + if (filep->f_oflags & O_NONBLOCK) + { + ret = -EAGAIN; + goto errout; + } + + /* Wait for sample data */ + + ret = gt9xx_waitsample(priv, buffer, len); + if (ret < 0) + { + /* We might have been awakened by a signal */ + + goto errout; + } + } + + ret = SIZEOF_TOUCH_SAMPLE_S(1); + +errout: + nxsem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Name: gt9xx_ioctl + ****************************************************************************/ + +static int gt9xx_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct gt9xx_dev_s *priv; + int ret; + + iinfo("cmd: %d arg: %ld\n", cmd, arg); + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct gt9xx_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + ierr("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + /* Process the IOCTL by command */ + + switch (cmd) + { + case TSIOC_SETFREQUENCY: /* arg: Pointer to uint32_t frequency value */ + { + FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg); + DEBUGASSERT(priv->config != NULL && ptr != NULL); + priv->frequency = *ptr; + } + break; + + case TSIOC_GETFREQUENCY: /* arg: Pointer to uint32_t frequency value */ + { + FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg); + DEBUGASSERT(priv->config != NULL && ptr != NULL); + *ptr = priv->frequency; + } + break; + + default: + ret = -ENOTTY; + break; + } + + nxsem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Name: gt9xx_poll + ****************************************************************************/ + +static int gt9xx_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct inode *inode; + FAR struct gt9xx_dev_s *priv; + int ret; + int i; + + iinfo("setup: %d\n", (int)setup); + DEBUGASSERT(filep && fds); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct gt9xx_dev_s *)inode->i_private; + + /* Are we setting up the poll? Or tearing it down? */ + + ret = nxsem_wait(&priv->devsem); + if (ret < 0) + { + ierr("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + if (setup) + { + /* Ignore waits that do not include POLLIN */ + + if ((fds->events & POLLIN) == 0) + { + ierr("ERROR: Missing POLLIN: revents: %08x\n", fds->revents); + ret = -EDEADLK; + goto errout; + } + + /* This is a request to set up the poll. Find an available + * slot for the poll structure reference + */ + + for (i = 0; i < CONFIG_GT9XX_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!priv->fds[i]) + { + /* Bind the poll structure and this slot */ + + priv->fds[i] = fds; + fds->priv = &priv->fds[i]; + break; + } + } + + if (i >= CONFIG_GT9XX_NPOLLWAITERS) + { + ierr("ERROR: No available slot found: %d\n", i); + fds->priv = NULL; + ret = -EBUSY; + goto errout; + } + + /* Should we immediately notify on any of the requested events? */ + + if (priv->valid) + { + gt9xx_notify(priv); + } + } + else if (fds->priv) + { + /* This is a request to tear down the poll. */ + + struct pollfd **slot = (struct pollfd **)fds->priv; + DEBUGASSERT(slot != NULL); + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +errout: + nxsem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gt9xx_register + * + * Description: + * Configure the GT9xx to use the provided I2C device instance. This + * will register the driver as /dev/inputN where N is the minor device + * number + * + * Input Parameters: + * dev - An I2C driver instance + * config - Persistent board configuration data + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int gt9xx_register(FAR struct i2c_master_s *i2c, + FAR const struct gt9xx_config_s *config, int minor) +{ + FAR struct gt9xx_dev_s *priv; + char devname[DEV_NAMELEN]; + int ret; + + iinfo("i2c: %p minor: %d\n", i2c, minor); + + /* Debug-only sanity checks */ + + DEBUGASSERT(i2c != NULL && config != NULL && minor >= 0 && minor < 100); +#ifdef CONFIG_GT9XX_POLLMODE + DEBUGASSERT(config->wakeup != NULL && config->nreset != NULL); +#else + DEBUGASSERT(config->attach != NULL && config->enable != NULL && + config->clear != NULL && config->wakeup != NULL && + config->nreset != NULL); +#endif + + /* Create and initialize a GT9xx device driver instance */ + + priv = (FAR struct gt9xx_dev_s *)kmm_zalloc(sizeof(struct gt9xx_dev_s)); + if (!priv) + { + ierr("ERROR: kmm_zalloc(%d) failed\n", sizeof(struct gt9xx_dev_s)); + return -ENOMEM; + } + + /* Initialize the GT9xx device driver instance */ + + priv->i2c = i2c; /* Save the I2C device handle */ + priv->config = config; /* Save the board configuration */ + priv->frequency = config->frequency; /* Set the current I2C frequency */ + + nxsem_init(&priv->devsem, 0, 1); /* Initialize device structure semaphore */ + nxsem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */ + + /* The event wait semaphore is used for signaling and, hence, should not + * have priority inheritance enabled. + */ + + nxsem_set_protocol(&priv->waitsem, SEM_PRIO_NONE); + +#ifdef CONFIG_GT9XX_POLLMODE + /* Allocate a timer for polling the GT9xx */ + priv->delay = POLL_MAXDELAY; +#else + /* Make sure that the GT9xx interrupt interrupt is disabled */ + + config->clear(config); + config->enable(config, false); + + /* Attach the interrupt handler */ + + ret = config->attach(config, gt9xx_data_interrupt, + priv); + if (ret < 0) + { + ierr("ERROR: Failed to attach interrupt\n"); + goto errout_with_priv; + } +#endif + + /* Register the device as an input device */ + + snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); + iinfo("Registering %s\n", devname); + + ret = register_driver(devname, >9xx_fops, 0666, priv); + if (ret < 0) + { + ierr("ERROR: register_driver() failed: %d\n", ret); + goto errout_with_priv; + } + + /* Schedule work to perform the initial sampling and to set the data + * availability conditions. + */ + + ret = work_queue(HPWORK, &priv->work, gt9xx_data_worker, priv, 0); + if (ret < 0) + { + ierr("ERROR: Failed to queue work: %d\n", ret); + goto errout_with_priv; + } + + /* And return success */ + + return OK; + +errout_with_priv: + nxsem_destroy(&priv->devsem); + kmm_free(priv); + return ret; +} diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/include/nuttx/input/gt9xx.h b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/include/nuttx/input/gt9xx.h new file mode 100755 index 000000000..1d723fa53 --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/include/nuttx/input/gt9xx.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2022 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +/** + * @file gt9xx.h + * @brief API for gt9xx. + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2022.5.31 + */ + + +#ifndef __GT9XX_H_ +#define __GT9XX_H_ + +#define GT9XX_MAX_TOUCHES (1) +#define GT9XX_TOUCH_DATA_LEN (8 * GT9XX_MAX_TOUCHES + 4) + +#define TOUCH_POINT_GET_EVENT(t) ((t).xh >> 6) +#define TOUCH_POINT_GET_ID(t) ((t).yh >> 4) +#define TOUCH_POINT_GET_X(t) ((((t).xh & 0x0f) << 8) | (t).xl) +#define TOUCH_POINT_GET_Y(t) ((((t).yh & 0x0f) << 8) | (t).yl) + + +#define GT9XX_MAX_HEIGHT 272 +#define GT9XX_MAX_WIDTH 480 +#define GT9XX_INT_TRIGGER 0 + +#define GT9XX_ADDR_LENGTH 2 +#define GT9XX_CONFIG_MIN_LENGTH 186 +#define GT9XX_CONFIG_MAX_LENGTH 240 + +#define GT9XX_REG_BAK_REF 0x99D0 +#define GT9XX_REG_MAIN_CLK 0x8020 +#define GT9XX_REG_CHIP_TYPE 0x8000 +#define GT9XX_REG_HAVE_KEY 0x804E +#define GT9XX_REG_MATRIX_DRVNUM 0x8069 +#define GT9XX_REG_MATRIX_SENNUM 0x806A +#define GT9XX_REG_COMMAND 0x8040 + +#define GT9XX_COMMAND_READSTATUS 0 +#define GT9XX_COMMAND_DIFFERENCE 1 +#define GT9XX_COMMAND_SOFTRESET 2 +#define GT9XX_COMMAND_UPDATE 3 +#define GT9XX_COMMAND_CALCULATE 4 +#define GT9XX_COMMAND_TURNOFF 5 + +#define GT9XX_REG_READ_COOR 0x814E +#define GT9XX_REG_SLEEP 0x8040 +#define GT9XX_REG_SENSOR_ID 0x814A +#define GT9XX_REG_CONFIG_DATA 0x8047 +#define GT9XX_REG_VERSION 0x8140 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +enum touch_event_e +{ + GT9XX_DOWN = 0, /* The state changed to touched */ + GT9XX_UP = 1, /* The state changed to not touched */ + GT9XX_CONTACT = 2, /* There is a continuous touch being detected */ + GT9XX_INVALID = 3 /* No touch information available */ +}; + +/* Describes on touchpoint returned by the GT9xx */ + +struct gt9xx_touch_point_s +{ + uint8_t xl; + uint8_t xh; + uint8_t yl; + uint8_t yh; + uint8_t weight; + uint8_t area; +}; + +/* Describes all touch data returned by the GT9xx */ + +struct gt9xx_touch_data_s +{ + uint8_t tdstatus; /* Touch status */ + struct gt9xx_touch_point_s touch[GT9XX_MAX_TOUCHES]; +}; + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Maximum number of threads than can be waiting for POLL events */ + +#ifndef CONFIG_GT9XX_NPOLLWAITERS +# define CONFIG_GT9XX_NPOLLWAITERS 2 +#endif + +/* Check for some required settings. This can save the user a lot of time + * in getting the right configuration. + */ + +#ifndef CONFIG_SCHED_WORKQUEUE +# error "Work queue support required. CONFIG_SCHED_WORKQUEUE must be selected." +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* A reference to a structure of this type must be passed to the GT9XX + * driver. This structure provides information about the configuration + * of the FT5x06 and provides some board-specific hooks. + * + * Memory for this structure is provided by the caller. It is not copied + * by the driver and is presumed to persist while the driver is active. The + * memory must be writeable because, under certain circumstances, the driver + * may modify frequency or X plate resistance values. + */ + +struct gt9xx_config_s +{ + /* Device characterization */ + + uint8_t address; /* 7-bit I2C address (only bits 0-6 used) */ + uint32_t frequency; /* Default I2C frequency */ + + /* IRQ/GPIO access callbacks. These operations all hidden behind + * callbacks to isolate the GT9XX driver from differences in GPIO + * interrupt handling by varying boards and MCUs. + * + * attach - Attach an FT5x06 interrupt handler to a GPIO interrupt + * enable - Enable or disable a GPIO interrupt + * clear - Acknowledge/clear any pending GPIO interrupt + * wakeup - Issue WAKE interrupt to FT5x06 to change the FT5x06 from + * Hibernate to Active mode. + * nreset - Control the chip reset pin (active low) + + */ + +#ifndef CONFIG_GT9XX_POLLMODE + int (*attach)(FAR const struct gt9xx_config_s *config, xcpt_t isr, + FAR void *arg); + void (*enable)(FAR const struct gt9xx_config_s *config, bool enable); + void (*clear)(FAR const struct gt9xx_config_s *config); +#endif + void (*wakeup)(FAR const struct gt9xx_config_s *config); + void (*nreset)(FAR const struct gt9xx_config_s *config, + bool state); +}; + + +int gt9xx_register(FAR struct i2c_master_s *i2c, + FAR const struct gt9xx_config_s *config, int minor); + + +#endif /* __GT9XX_H__ */