| /**************************************************************************** |
| * apps/graphics/ft80x/ft80x_touch.c |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| |
| #include <sys/ioctl.h> |
| #include <stdint.h> |
| #include <signal.h> |
| #include <assert.h> |
| #include <errno.h> |
| #include <unistd.h> |
| |
| #include <nuttx/lcd/ft80x.h> |
| |
| #include "graphics/ft80x.h" |
| #include "ft80x.h" |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: ft80x_touch_gettransform |
| * |
| * Description: |
| * Read the touch transform matrix |
| * |
| * Input Parameters: |
| * fd - The file descriptor of the FT80x device. Opened by the caller |
| * with write access. |
| * matrix - The location to return the transform matrix |
| * |
| * Returned Value: |
| * Zero (OK) on success. A negated errno value on failure. |
| * |
| ****************************************************************************/ |
| |
| int ft80x_touch_gettransform(int fd, FAR uint32_t matrix[6]) |
| { |
| int ret; |
| |
| /* Read FT80X_REG_TOUCH_TRANSFORM_A through FT80X_REG_TOUCH_TRANSFORM_F */ |
| |
| #ifdef CONFIG_LCD_FT800 |
| ret = ft80x_getregs(fd, FT80X_REG_TOUCH_TRANSFORM_A, 6, matrix); |
| #else |
| ret = ft80x_getregs(fd, FT80X_REG_CTOUCH_TRANSFORM_A, 6, matrix); |
| #endif |
| |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getregs failed: %d\n", ret); |
| } |
| |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: ft80x_touch_tag |
| * |
| * Description: |
| * Read the current touch tag. The touch tag is an 8-bit value |
| * identifying the specific graphics object on the screen that is being |
| * touched. The value zero indicates that there is no graphic object being |
| * touched. |
| * |
| * Only a single touch can be queried. For the FT801 in "extended", |
| * multi-touch mode, this value indicates only the tag associated with |
| * touch 0. |
| * |
| * Input Parameters: |
| * fd - The file descriptor of the FT80x device. Opened by the caller |
| * with write access. |
| * |
| * Returned Value: |
| * A value of 1-255 is returned if a graphics object is touched. Zero is |
| * returned if no graphics object is touched. A negated errno value on |
| * failure. |
| * |
| ****************************************************************************/ |
| |
| int ft80x_touch_tag(int fd) |
| { |
| uint8_t tag; |
| int ret; |
| |
| #if defined(CONFIG_LCD_FT800) |
| /* Read REG_TOUCH_TAG */ |
| |
| ret = ft80x_getreg8(fd, FT80X_REG_TOUCH_TAG, &tag); |
| |
| #elif defined(CONFIG_LCD_FT801) |
| /* Read REG_CTOUCH_TAG */ |
| |
| ret = ft80x_getreg8(fd, FT80X_REG_CTOUCH_TAG, &tag); |
| |
| #endif |
| |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg8 failed: %d\n", ret); |
| return ret; |
| } |
| |
| return (int)tag; |
| } |
| |
| /**************************************************************************** |
| * Name: ft80x_touch_waittag |
| * |
| * Description: |
| * Wait until there is a change in the touch tag. |
| * |
| * Input Parameters: |
| * fd - The file descriptor of the FT80x device. Opened by the caller |
| * with write access. |
| * oldtag - The previous tag value. This function will return when the |
| * current touch tag differs from this value. |
| * |
| * Returned Value: |
| * A value of 1-255 is returned if a graphics object is touched. Zero is |
| * returned if no graphics object is touched. A negated errno value on |
| * failure. |
| * |
| ****************************************************************************/ |
| |
| int ft80x_touch_waittag(int fd, uint8_t oldtag) |
| { |
| struct ft80x_notify_s notify; |
| struct timespec timeout; |
| sigset_t set; |
| uint8_t tag; |
| int ret; |
| |
| /* Block the signal so that it will pend if received asynchronously */ |
| |
| sigemptyset(&set); |
| sigaddset(&set, CONFIG_GRAPHICS_FT80X_TAG_SIGNAL); |
| |
| ret = pthread_sigmask(SIG_BLOCK, &set, NULL); |
| if (ret < 0) |
| { |
| ret = -errno; |
| ft80x_err("ERROR: pthread_sigmask for signal %d failed: %d\n", |
| CONFIG_GRAPHICS_FT80X_TAG_SIGNAL, ret); |
| return ret; |
| } |
| |
| notify.event.sigev_notify = SIGEV_SIGNAL; |
| notify.event.sigev_signo = CONFIG_GRAPHICS_FT80X_TAG_SIGNAL; |
| |
| notify.pid = getpid(); |
| notify.id = FT80X_NOTIFY_TAG; |
| notify.enable = false; |
| |
| for (; ; ) |
| { |
| /* Read the current touch tag. */ |
| |
| ret = ft80x_touch_tag(fd); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_touch_tag failed: %d\n", ret); |
| return ret; |
| } |
| |
| /* Check if the touch tag has already changed */ |
| |
| tag = (uint8_t)(ret & 0xff); |
| ft80x_info("oldtag=%u tag=%u\n", oldtag, tag); |
| |
| if (tag == oldtag) |
| { |
| /* The tag has changed... return success */ |
| |
| ret = OK; |
| break; |
| } |
| |
| /* Set up to receive a notification when the touch tag changes. |
| * NOTE that there is a race condition here between the preceding test |
| * and the time when the event is registered. We catch this with a |
| * timeout below. |
| */ |
| |
| notify.enable = true; |
| ret = ioctl(fd, FT80X_IOC_EVENTNOTIFY, |
| (unsigned long)((uintptr_t)¬ify)); |
| if (ret < 0) |
| { |
| ret = -errno; |
| ft80x_err("ERROR: ioctl(FT80X_IOC_EVENTNOTIFY) failed: %d\n", ret); |
| break; |
| } |
| |
| /* Now wait for the signal event (or a timeout) */ |
| |
| timeout.tv_sec = 0; |
| timeout.tv_nsec = 400 * 1000 * 1000; |
| |
| ret = sigtimedwait(&set, NULL, &timeout); |
| |
| /* Make sure that the event notification is again disabled */ |
| |
| notify.enable = false; |
| ioctl(fd, FT80X_IOC_EVENTNOTIFY, |
| (unsigned long)((uintptr_t)¬ify)); |
| |
| /* Check if the signal was received correctly or if the timeout |
| * occurred. |
| */ |
| |
| if (ret < 0) |
| { |
| int errcode = errno; |
| if (errcode != EAGAIN) |
| { |
| ft80x_err("ERROR: ioctl(FT80X_IOC_EVENTNOTIFY) failed: %d\n", |
| errcode); |
| ret = -errcode; |
| break; |
| } |
| } |
| } |
| |
| pthread_sigmask(SIG_UNBLOCK, &set, NULL); |
| return tag; |
| } |
| |
| /**************************************************************************** |
| * Name: ft80x_touch_info |
| * |
| * Description: |
| * Return the current touch tag and touch position information. |
| * |
| * For the FT801 in "extended", multi-touch mode, the tag value indicates |
| * only the tag associated with touch 0. |
| * |
| * Touch positions of -32768 indicate that no touch is detected. |
| * |
| * Input Parameters: |
| * fd - The file descriptor of the FT80x device. Opened by the caller |
| * with write access. |
| * info - Location in which to return the touch information |
| * |
| * Returned Value: |
| * A value of 1-255 is returned if a graphics object is touched. Zero is |
| * returned if no graphics object is touched. A negated errno value on |
| * failure. |
| * |
| ****************************************************************************/ |
| |
| int ft80x_touch_info(int fd, FAR struct ft80x_touchinfo_s *info) |
| { |
| int ret; |
| |
| DEBUGASSERT(info != NULL); |
| |
| #if defined(CONFIG_LCD_FT800) |
| /* Read REG_TOUCH_TAG */ |
| |
| ret = ft80x_getreg8(fd, FT80X_REG_TOUCH_TAG, &info->tag); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg8 failed: %d\n", ret); |
| return ret; |
| } |
| |
| /* Read the FT80X_REG_TOUCH_TAG_XY register */ |
| |
| ret = ft80x_getreg32(fd, FT80X_REG_TOUCH_TAG_XY, &info->tagpos.xy); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg32 failed: %d\n", ret); |
| return ret; |
| } |
| |
| /* Read the FT80X_REG_TOUCH_RZ register */ |
| |
| ret = ft80x_getreg16(fd, FT80X_REG_TOUCH_RZ, |
| (FAR uint16_t *)&info->pressure); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg16 failed: %d\n", ret); |
| return ret; |
| } |
| |
| /* Read the FT80X_REG_TOUCH_SCREEN_XY register */ |
| |
| ret = ft80x_getreg32(fd, FT80X_REG_TOUCH_SCREEN_XY, &info->pos.xy); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg32 failed: %d\n", ret); |
| return ret; |
| } |
| |
| #elif defined(CONFIG_LCD_FT801) |
| /* Read REG_CTOUCH_TAG */ |
| |
| ret = ft80x_getreg8(fd, FT80X_REG_CTOUCH_TAG, &info->tag); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg8 failed: %d\n", ret); |
| return ret; |
| } |
| |
| /* Read the FT80X_REG_CTOUCH_TAG_XY register */ |
| |
| ret = ft80x_getreg32(fd, FT80X_REG_CTOUCH_TAG_XY, &info->tagpos.xy); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg32 failed: %d\n", ret); |
| return ret; |
| } |
| |
| #ifndef CONFIG_LCD_FT801_MULTITOUCH |
| /* Read the FT80X_REG_CTOUCH_TOUCH0_XY register */ |
| |
| ret = ft80x_getreg32(fd, FT80X_REG_CTOUCH_TOUCH0_XY, &info->pos.xy); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg32 failed: %d\n", ret); |
| return ret; |
| } |
| |
| #else |
| /* Read the FT80X_REG_CTOUCH_TOUCH0_XY register */ |
| |
| ret = ft80x_getreg32(fd, FT80X_REG_CTOUCH_TOUCH0_XY, &info->pos[0].xy); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg32 failed: %d\n", ret); |
| return ret; |
| } |
| |
| /* Read the FT80X_REG_CTOUCH_TOUCH1_XY register */ |
| |
| ret = ft80x_getreg32(fd, FT80X_REG_CTOUCH_TOUCH1_XY, &info->pos[1].xy); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg32 failed: %d\n", ret); |
| return ret; |
| } |
| |
| /* Read the FT80X_REG_CTOUCH_TOUCH2_XY register */ |
| |
| ret = ft80x_getreg32(fd, FT80X_REG_CTOUCH_TOUCH2_XY, &info->pos[2].xy); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg32 failed: %d\n", ret); |
| return ret; |
| } |
| |
| /* Read the FT80X_REG_CTOUCH_TOUCH3_XY register */ |
| |
| ret = ft80x_getreg32(fd, FT80X_REG_CTOUCH_TOUCH3_XY, &info->pos[3].xy); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg32 failed: %d\n", ret); |
| return ret; |
| } |
| |
| /* Read the FT80X_REG_CTOUCH_TOUCH4_X and Y registers */ |
| |
| ret = ft80x_getreg16(fd, FT80X_REG_CTOUCH_TOUCH4_X, |
| (FAR uint16_t *)&info->pos[4].u.x); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg16 failed: %d\n", ret); |
| return ret; |
| } |
| |
| ret = ft80x_getreg16(fd, FT80X_REG_CTOUCH_TOUCH4_Y, |
| (FAR uint16_t *)&info->pos[4].u.y); |
| if (ret < 0) |
| { |
| ft80x_err("ERROR: ft80x_getreg16 failed: %d\n", ret); |
| return ret; |
| } |
| |
| #endif /* CONFIG_LCD_FT801_MULTITOUCH */ |
| #endif /* CONFIG_LCD_FT800/1 */ |
| |
| return OK; |
| } |