diff --git a/Documentation/platforms/arm/stm32h7/boards/linum-stm32h753bi/index.rst b/Documentation/platforms/arm/stm32h7/boards/linum-stm32h753bi/index.rst index bcf7064e6a0..ddecaf0a05e 100644 --- a/Documentation/platforms/arm/stm32h7/boards/linum-stm32h753bi/index.rst +++ b/Documentation/platforms/arm/stm32h7/boards/linum-stm32h753bi/index.rst @@ -232,7 +232,7 @@ EEPROM memory used is the 24LC256 with 256Kb with the control bytes value 0x54. TOUCHSCREEN SENSOR ------------------ -The touchscreen sensor used is the GT928. +The touchscreen sensor used is the FT5X06. ======== ===== GPIO PINS @@ -817,7 +817,37 @@ Configures the board to use the SPI4 and enables RFID driver with MFRC522:: lvgl ---- -Configures the board to use display of 7 inch with lvgl example. +Configures the board to use display of 7 inch with lvgl example. The touch screen functionality is implemented using +the FT5X06 capacitive touch controller connected to I2C3 interface, with interrupt handling configured on pin PH9 for touch event detection. + +To verify if the touch controller is functioning correctly, use the **tc** command.:: + + nsh> tc 2 + tc_main: nsamples: 2 + tc_main: Opening /dev/input0 + Sample : + npoints : 1 + Point 1 : + id : 0 + flags : 19 + x : 0 + y : 52 + h : 0 + w : 0 + pressure : 0 + timestamp : 0 + Sample : + npoints : 1 + Point 1 : + id : 0 + flags : 1a + x : 0 + y : 52 + h : 0 + w : 0 + pressure : 0 + timestamp : 0 + Terminating! To verify if the display is functioning correctly, use the **fb** command. You should see the display change colors.:: @@ -862,11 +892,11 @@ Once the **fd** command work, run the lvgl exemple. :: **WARNING:** This example at the moment is not working correctly yet and have a bug fix to be done. In the lvgl file **./apps/graphics/lvgl/lvgl/src/drivers/nuttx/lv_nuttx_fbdev.c** -search the function **lv_nuttx_fbdev_set_file** and modify line 156 as follows: +search the function **lv_nuttx_fbdev_set_file** and modify line 156 as follows:: dsc->mem_off_screen = malloc(data_size); to - dsc->mem_off_screen = (void*)0xC00000000; + dsc->mem_off_screen = (void*)0xC0000000; tone ---- diff --git a/boards/arm/stm32h7/linum-stm32h753bi/configs/lvgl/defconfig b/boards/arm/stm32h7/linum-stm32h753bi/configs/lvgl/defconfig index f691a1efa4c..a167a5b30cf 100644 --- a/boards/arm/stm32h7/linum-stm32h753bi/configs/lvgl/defconfig +++ b/boards/arm/stm32h7/linum-stm32h753bi/configs/lvgl/defconfig @@ -30,10 +30,14 @@ CONFIG_DRIVERS_VIDEO=y CONFIG_EXAMPLES_ALARM=y CONFIG_EXAMPLES_FB=y CONFIG_EXAMPLES_LVGLDEMO=y +CONFIG_EXAMPLES_TOUCHSCREEN=y CONFIG_FB_OVERLAY=y CONFIG_FS_PROCFS=y +CONFIG_FT5X06_SINGLEPOINT=y CONFIG_GRAPHICS_LVGL=y CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INPUT=y +CONFIG_INPUT_FT5X06=y CONFIG_INTELHEX_BINARY=y CONFIG_LIBM=y CONFIG_LINE_MAX=64 @@ -42,6 +46,7 @@ CONFIG_LV_USE_CLIB_SPRINTF=y CONFIG_LV_USE_CLIB_STRING=y CONFIG_LV_USE_DEMO_WIDGETS=y CONFIG_LV_USE_NUTTX=y +CONFIG_LV_USE_NUTTX_TOUCHSCREEN=y CONFIG_MM_REGIONS=5 CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y @@ -56,11 +61,13 @@ CONFIG_RR_INTERVAL=200 CONFIG_RTC_ALARM=y CONFIG_RTC_DATETIME=y CONFIG_RTC_DRIVER=y +CONFIG_SCHED_HPWORK=y CONFIG_SCHED_WAITPID=y CONFIG_START_DAY=6 CONFIG_START_MONTH=12 CONFIG_START_YEAR=2011 CONFIG_STM32H7_FMC=y +CONFIG_STM32H7_I2C3=y CONFIG_STM32H7_LTDC=y CONFIG_STM32H7_LTDC_FB_BASE=0xC0000000 CONFIG_STM32H7_LTDC_FB_SIZE=1228800 diff --git a/boards/arm/stm32h7/linum-stm32h753bi/include/board.h b/boards/arm/stm32h7/linum-stm32h753bi/include/board.h index b68233c9a9a..0470c4832bf 100644 --- a/boards/arm/stm32h7/linum-stm32h753bi/include/board.h +++ b/boards/arm/stm32h7/linum-stm32h753bi/include/board.h @@ -412,11 +412,18 @@ #define GPIO_SDMMC1_D2 (GPIO_SDMMC1_D2_0|GPIO_SPEED_100MHz) /* PC10 */ #define GPIO_SDMMC1_D3 (GPIO_SDMMC1_D3_0|GPIO_SPEED_100MHz) /* PC11 */ -/* I2C3 - Used by eeprom memory */ +/* I2C3 - Used by eeprom memory and touch screen */ #define GPIO_I2C3_SCL (GPIO_I2C3_SCL_2|GPIO_SPEED_100MHz) /* PH7 */ #define GPIO_I2C3_SDA (GPIO_I2C3_SDA_2|GPIO_SPEED_100MHz) /* PH8 */ +/* I2C - There is a FT5336 TouchPanel on I2C3 using these pins: */ + +#define ADJ_SLEW_RATE(p) (((p) & ~GPIO_SPEED_MASK) | (GPIO_SPEED_100MHz)) +#define GPIO_TP_INT (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTH|GPIO_PIN9) /* PH9 */ + +#define FT5X06_I2C_ADDRESS (0x38) + /* PWM - Buzzer */ #define GPIO_TIM4_CH2OUT (GPIO_TIM4_CH2OUT_1|GPIO_SPEED_100MHz) /* PB7 */ diff --git a/boards/arm/stm32h7/linum-stm32h753bi/src/CMakeLists.txt b/boards/arm/stm32h7/linum-stm32h753bi/src/CMakeLists.txt index fa58e34bf2e..4062f4dfe66 100644 --- a/boards/arm/stm32h7/linum-stm32h753bi/src/CMakeLists.txt +++ b/boards/arm/stm32h7/linum-stm32h753bi/src/CMakeLists.txt @@ -78,6 +78,10 @@ if(CONFIG_STM32H7_LTDC) list(APPEND SRCS stm32_lcd.c) endif() +if(CONFIG_INPUT_FT5X06) + list(APPEND SRCS stm32_touchscreen.c) +endif() + target_sources(board PRIVATE ${SRCS}) set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/flash.ld") diff --git a/boards/arm/stm32h7/linum-stm32h753bi/src/Makefile b/boards/arm/stm32h7/linum-stm32h753bi/src/Makefile index ca57095d09a..e8adde244ed 100644 --- a/boards/arm/stm32h7/linum-stm32h753bi/src/Makefile +++ b/boards/arm/stm32h7/linum-stm32h753bi/src/Makefile @@ -80,4 +80,8 @@ ifeq ($(CONFIG_AUDIO_TONE),y) CSRCS += stm32_tone.c endif +ifeq ($(CONFIG_INPUT_FT5X06),y) +CSRCS += stm32_touchscreen.c +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/stm32h7/linum-stm32h753bi/src/linum-stm32h753bi.h b/boards/arm/stm32h7/linum-stm32h753bi/src/linum-stm32h753bi.h index 47f21873451..0a77493a73b 100644 --- a/boards/arm/stm32h7/linum-stm32h753bi/src/linum-stm32h753bi.h +++ b/boards/arm/stm32h7/linum-stm32h753bi/src/linum-stm32h753bi.h @@ -287,4 +287,25 @@ int stm32_mfrc522initialize(const char *devpath); int board_tone_initialize(int devno); #endif +/**************************************************************************** + * Name: stm32_tsc_setup + * + * Description: + * This function is called by board-bringup logic to configure the + * touchscreen device. This function will register the driver as + * /dev/inputN where N is the minor device number. + * + * Input Parameters: + * 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. + * + ****************************************************************************/ + +#ifdef CONFIG_INPUT_FT5X06 +int stm32_tsc_setup(int minor); +#endif + #endif /* __BOARDS_ARM_STM32H7_LINUM_STM32H753BI_SRC_LINUM_STM32H753BI_H */ diff --git a/boards/arm/stm32h7/linum-stm32h753bi/src/stm32_bringup.c b/boards/arm/stm32h7/linum-stm32h753bi/src/stm32_bringup.c index 366acba1823..ebe03e69b2b 100644 --- a/boards/arm/stm32h7/linum-stm32h753bi/src/stm32_bringup.c +++ b/boards/arm/stm32h7/linum-stm32h753bi/src/stm32_bringup.c @@ -353,5 +353,15 @@ int stm32_bringup(void) } #endif +#ifdef CONFIG_INPUT_FT5X06 + /* Initialize the touchscreen */ + + ret = stm32_tsc_setup(0); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_tsc_setup failed: %d\n", ret); + } +#endif + return OK; } diff --git a/boards/arm/stm32h7/linum-stm32h753bi/src/stm32_touchscreen.c b/boards/arm/stm32h7/linum-stm32h753bi/src/stm32_touchscreen.c new file mode 100644 index 00000000000..1277b65db45 --- /dev/null +++ b/boards/arm/stm32h7/linum-stm32h753bi/src/stm32_touchscreen.c @@ -0,0 +1,298 @@ +/**************************************************************************** + * boards/arm/stm32h7/linum-stm32h753bi/src/stm32_touchscreen.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "stm32_gpio.h" +#include "stm32_i2c.h" + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define FT5X06_FREQUENCY 100000 /* For now, will boost later */ + +#ifdef CONFIG_INPUT_FT5X06 +#ifndef CONFIG_INPUT +# error "FT5x06 support requires CONFIG_INPUT" +#endif + +#ifndef CONFIG_STM32H7_I2C3 +# error "FT5x06 support requires CONFIG_STM32H7_I2C3" +#endif + +#ifndef CONFIG_FT5X06_I2CDEV +# define CONFIG_FT5X06_I2CDEV 3 +#endif + +#if CONFIG_FT5X06_I2CDEV != 3 +# error "CONFIG_FT5X06_I2CDEV must be three" +#endif + +#ifndef CONFIG_FT5X06_DEVMINOR +# define CONFIG_FT5X06_DEVMINOR 0 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct stm32_ft5x06_config_s +{ + xcpt_t handler; /* The FT5x06 interrupt handler */ + void *arg; /* Interrupt handler argument */ +}; + +/**************************************************************************** + * Private Function Ptototypes + ****************************************************************************/ + +#ifndef CONFIG_FT5X06_POLLMODE +static int stm32_ft5x06_attach(const struct ft5x06_config_s *config, + xcpt_t isr, void *arg); +static void stm32_ft5x06_enable(const struct ft5x06_config_s *config, + bool enable); +static void stm32_ft5x06_clear(const struct ft5x06_config_s *config); +#endif +static void stm32_ft5x06_wakeup(const struct ft5x06_config_s *config); +static void stm32_ft5x06_nreset(const struct ft5x06_config_s *config, + bool state); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct ft5x06_config_s g_ft5x06_config = +{ + .address = FT5X06_I2C_ADDRESS, + .frequency = FT5X06_FREQUENCY, +#ifndef CONFIG_FT5X06_POLLMODE + .attach = stm32_ft5x06_attach, + .enable = stm32_ft5x06_enable, + .clear = stm32_ft5x06_clear, +#endif + .wakeup = stm32_ft5x06_wakeup, + .nreset = stm32_ft5x06_nreset +}; + +static struct stm32_ft5x06_config_s g_priv_config = +{ + .handler = NULL, + .arg = NULL, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_ft5x06_attach + * + * Description: + * Attach an FT5x06 interrupt handler to a GPIO interrupt + * + ****************************************************************************/ + +#ifndef CONFIG_FT5X06_POLLMODE +static int stm32_ft5x06_attach(const struct ft5x06_config_s *config, + xcpt_t isr, void *arg) +{ + iinfo("Saving handler %p\n", isr); + + /* Just save the handler. We will use it when EXTI interruptsare enabled */ + + if (isr) + { + /* Just save the address of the handler for now. The new handler will + * be attached when the interrupt is next enabled. + */ + + iinfo("Attaching %p\n", isr); + g_priv_config.handler = isr; + g_priv_config.arg = arg; + } + else + { + iinfo("Detaching %p\n", g_priv_config.handler); + stm32_ft5x06_enable(config, false); + g_priv_config.handler = NULL; + g_priv_config.arg = NULL; + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: stm32_ft5x06_enable + * + * Description: + * Enable or disable a GPIO interrupt + * + ****************************************************************************/ + +#ifndef CONFIG_FT5X06_POLLMODE +static void stm32_ft5x06_enable(const struct ft5x06_config_s *config, + bool enable) +{ + irqstate_t flags; + + /* Attach and enable, or detach and disable. Enabling and disabling GPIO + * interrupts is a multi-step process so the safest thing is to keep + * interrupts disabled during the reconfiguration. + */ + + flags = enter_critical_section(); + if (enable) + { + /* Configure the EXTI interrupt using the SAVED handler */ + + stm32_gpiosetevent(GPIO_TP_INT, true, false, true, + g_priv_config.handler, g_priv_config.arg); + } + else + { + /* Configure the EXTI interrupt with a NULL handler to disable it */ + + stm32_gpiosetevent(GPIO_TP_INT, false, false, false, + NULL, NULL); + } + + leave_critical_section(flags); +} +#endif + +/**************************************************************************** + * Name: stm32_ft5x06_clear + * + * Description: + * Acknowledge/clear any pending GPIO interrupt + * + ****************************************************************************/ + +#ifndef CONFIG_FT5X06_POLLMODE +static void stm32_ft5x06_clear(const struct ft5x06_config_s *config) +{ + /* Does nothing */ +} +#endif + +/**************************************************************************** + * Name: stm32_ft5x06_wakeup + * + * Description: + * Issue WAKE interrupt to FT5x06 to change the FT5x06 from Hibernate to + * Active mode. + * + ****************************************************************************/ + +static void stm32_ft5x06_wakeup(const struct ft5x06_config_s *config) +{ + /* We do not have access to the WAKE pin in the implementation */ +} + +/**************************************************************************** + * Name: stm32_ft5x06_nreset + * + * Description: + * Control the chip reset pin + * + ****************************************************************************/ + +static void stm32_ft5x06_nreset(const struct ft5x06_config_s *config, + bool nstate) +{ + /* We do not have access to the RESET pin in the implementation */ +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_tsc_setup + * + * Description: + * This function is called by board-bringup logic to configure the + * touchscreen device. This function will register the driver as + * /dev/inputN where N is the minor device number. + * + * Input Parameters: + * 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 stm32_tsc_setup(int minor) +{ + struct i2c_master_s *dev; + int ret; + + iinfo("minor %d\n", minor); + DEBUGASSERT(minor == CONFIG_FT5X06_DEVMINOR); + + /* Check if we are already initialized */ + + iinfo("Initializing\n"); + + /* Configure the FT5X06 interrupt pin as an input */ + + stm32_configgpio(GPIO_TP_INT); + + /* Get an instance of the I2C interface */ + + dev = stm32_i2cbus_initialize(CONFIG_FT5X06_I2CDEV); + if (!dev) + { + ierr("ERROR: Failed to initialize I2C bus %d\n", CONFIG_FT5X06_I2CDEV); + return -ENODEV; + } + + /* Initialize and register the I2C touchscreen device */ + + ret = ft5x06_register(dev, &g_ft5x06_config, CONFIG_FT5X06_DEVMINOR); + if (ret < 0) + { + ierr("ERROR: Failed to register FT5x06 driver: %d\n", ret); + stm32_i2cbus_uninitialize(dev); + return ret; + } + + return OK; +} + +#endif /* CONFIG_INPUT_FT5X06 */