1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

drivers/ft5x06: add touch panel driver

This commit is contained in:
Alexandre Abadie 2021-12-27 11:24:39 +01:00
parent c5656ef3b2
commit 11f73ea5c9
No known key found for this signature in database
GPG Key ID: 1C919A403CAE1405
10 changed files with 658 additions and 0 deletions

View File

@ -76,6 +76,7 @@ rsource "dcf77/Kconfig"
rsource "dht/Kconfig"
rsource "ds18/Kconfig"
rsource "ds75lx/Kconfig"
rsource "ft5x06/Kconfig"
rsource "fxos8700/Kconfig"
rsource "gp2y10xx/Kconfig"
rsource "hdc1000/Kconfig"

View File

@ -52,6 +52,10 @@ ifneq (,$(filter ethos_%,$(USEMODULE)))
USEMODULE += ethos
endif
ifneq (,$(filter ft6% ft5% ft3%,$(USEMODULE)))
USEMODULE += ft5x06
endif
ifneq (,$(filter hmc5883l_%,$(USEMODULE)))
USEMODULE += hmc5883l
endif

109
drivers/ft5x06/Kconfig Normal file
View File

@ -0,0 +1,109 @@
# Copyright (c) 2021 Inria
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
config MODULE_FT5X06
bool "FT5X06 touch panel driver"
depends on TEST_KCONFIG
depends on HAS_PERIPH_GPIO_IRQ
depends on HAS_PERIPH_I2C
select MODULE_PERIPH_GPIO_IRQ
select MODULE_PERIPH_I2C
select MODULE_ZTIMER
select MODULE_ZTIMER_MSEC
config MODULE_FT5606
bool "FT5606 touch panel driver"
select MODULE_FT5X06
config MODULE_FT5X16
bool "FT5X16 touch panel driver"
select MODULE_FT5X06
config MODULE_FT6X06
bool "FT6X06 touch panel driver"
select MODULE_FT5X06
config MODULE_FT6X36
bool "FT6X36 touch panel driver"
select MODULE_FT5X06
config MODULE_FT5X06I
bool "FT5X06I touch panel driver"
select MODULE_FT5X06
config MODULE_FT5336
bool "FT5336 touch panel driver"
select MODULE_FT5X06
config MODULE_FT3316
bool "FT3316 touch panel driver"
select MODULE_FT5X06
config MODULE_FT5436I
bool "FT5436I touch panel driver"
select MODULE_FT5X06
config MODULE_FT5336I
bool "FT5336I touch panel driver"
select MODULE_FT5X06
config MODULE_FT5X46
bool "FT5X46 touch panel driver"
select MODULE_FT5X06
config HAVE_FT5606
bool
select MODULE_FT5606 if MODULE_TOUCH_DEV
help
Indicates that an FT5606 touch panel is present.
config HAVE_FT5X16
bool
select MODULE_FT5X16 if MODULE_TOUCH_DEV
help
Indicates that an FT5X16 touch panel is present.
config HAVE_FT6X06
bool
select MODULE_FT6X06 if MODULE_TOUCH_DEV
help
Indicates that an FT6X06 touch panel is present.
config HAVE_FT6X36
bool
select MODULE_FT6X36 if MODULE_TOUCH_DEV
help
Indicates that an FT6X36 touch panel is present.
config HAVE_FT5X06I
bool
select MODULE_FT5X06I if MODULE_TOUCH_DEV
help
Indicates that an FT5X06I touch panel is present.
config HAVE_FT5336
bool
select MODULE_FT5336 if MODULE_TOUCH_DEV
help
Indicates that an FT5336 touch panel is present.
config HAVE_FT3316
bool
select MODULE_FT3316 if MODULE_TOUCH_DEV
help
Indicates that an FT3316 touch panel is present.
config HAVE_FT5436I
bool
select MODULE_FT5436I if MODULE_TOUCH_DEV
help
Indicates that an FT5436I touch panel is present.
config HAVE_FT5X46
bool
select MODULE_FT5X46 if MODULE_TOUCH_DEV
help
Indicates that an FT5X46 touch panel is present.

1
drivers/ft5x06/Makefile Normal file
View File

@ -0,0 +1 @@
include $(RIOTMAKE)/driver_with_touch_dev.mk

View File

@ -0,0 +1,5 @@
FEATURES_REQUIRED += periph_gpio_irq
FEATURES_REQUIRED += periph_i2c
USEMODULE += ztimer
USEMODULE += ztimer_msec

View File

@ -0,0 +1,13 @@
USEMODULE_INCLUDES_ft5x06 := $(LAST_MAKEFILEDIR)/include
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_ft5x06)
PSEUDOMODULES += ft5606
PSEUDOMODULES += ft5x16
PSEUDOMODULES += ft6x06
PSEUDOMODULES += ft6x36
PSEUDOMODULES += ft5x06i
PSEUDOMODULES += ft5336
PSEUDOMODULES += ft3316
PSEUDOMODULES += ft5436i
PSEUDOMODULES += ft5336i
PSEUDOMODULES += ft5x46

157
drivers/ft5x06/ft5x06.c Normal file
View File

@ -0,0 +1,157 @@
/*
* Copyright (C) 2021 Inria
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_ft5x06
* @{
*
* @file
* @brief Device driver implementation for the FT5x06 touch driver
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*
* @}
*/
#include <errno.h>
#include <stdint.h>
#include "periph/i2c.h"
#include "periph/gpio.h"
#include "ztimer.h"
#include "ft5x06.h"
#include "ft5x06_constants.h"
#include "ft5x06_params.h"
#define ENABLE_DEBUG 0
#include "debug.h"
#define FT5X06_BUS (dev->params.i2c)
#define FT5X06_ADDR (dev->params.addr)
#define FT5X06_RESET_DELAY_MS (200)
int ft5x06_init(ft5x06_t *dev, const ft5x06_params_t *params, ft5x06_event_cb_t cb, void *arg)
{
dev->params = *params;
/* Wait at least 200ms after power up before accessing registers */
ztimer_sleep(ZTIMER_MSEC, FT5X06_RESET_DELAY_MS);
i2c_acquire(FT5X06_BUS);
uint8_t vendor_id = 0;
if (i2c_read_reg(FT5X06_BUS, FT5X06_ADDR, FT5X06_G_VENDOR_ID_REG, &vendor_id, 0) != 0) {
i2c_release(FT5X06_BUS);
return -EPROTO;
}
if (vendor_id != FT5X06_VENDOR_ID) {
DEBUG("[ft5x06] init: invalid vendor ID: '0x%02x' (expected: 0x%02x)\n",
vendor_id, FT5X06_VENDOR_ID);
i2c_release(FT5X06_BUS);
return -ENODEV;
}
/* Auto-calibrate if needed */
if (IS_ACTIVE(FT5X06_AUTO_CALIB_NEEDED)) {
DEBUG("[ft5x06] init: enable device auto-calibration\n");
i2c_write_reg(FT5X06_BUS, FT5X06_ADDR, FT5X06_G_AUTO_CLB_MODE_REG, 0, 0);
}
/* Configure interrupt */
if (gpio_is_valid(dev->params.int_pin)) {
DEBUG("[ft5x06] init: configuring touchscreen interrupt\n");
gpio_init_int(dev->params.int_pin, GPIO_IN, GPIO_RISING, cb, arg);
i2c_write_reg(FT5X06_BUS, FT5X06_ADDR, FT5X06_G_MODE_REG, FT5X06_G_MODE_INTERRUPT_TRIGGER & 0x01, 0);
}
i2c_release(FT5X06_BUS);
return 0;
}
static const uint8_t touch_reg_map[FT5X06_TOUCHES_COUNT_MAX] = {
FT5X06_TOUCH1_XH_REG,
FT5X06_TOUCH2_XH_REG,
#if FT5X06_TOUCHES_COUNT_MAX > 2
FT5X06_TOUCH3_XH_REG,
FT5X06_TOUCH4_XH_REG,
FT5X06_TOUCH5_XH_REG,
#endif
};
int ft5x06_read_touch_positions(const ft5x06_t *dev, ft5x06_touch_position_t *positions, size_t len)
{
i2c_acquire(FT5X06_BUS);
for (uint8_t touch = 0; touch < len; touch++) {
uint8_t regs[4];
uint16_t pos_x = 0, pos_y = 0;
i2c_read_regs(FT5X06_BUS, FT5X06_ADDR, touch_reg_map[touch], &regs, 4, 0);
pos_x = (uint16_t)((regs[1] & FT5X06_TOUCH_POS_LSB_MASK) | (uint16_t)(regs[0] & FT5X06_TOUCH_POS_MSB_MASK) << 8);
pos_y = (uint16_t)((regs[3] & FT5X06_TOUCH_POS_LSB_MASK) | (uint16_t)(regs[2] & FT5X06_TOUCH_POS_MSB_MASK) << 8);
/* X and Y positions are swapped compared to the display */
positions[touch].x = pos_y;
positions[touch].y = pos_x;
}
i2c_release(FT5X06_BUS);
return 0;
}
int ft5x06_read_touch_count(const ft5x06_t *dev, uint8_t *count)
{
i2c_acquire(FT5X06_BUS);
i2c_read_reg(FT5X06_BUS, FT5X06_ADDR, FT5X06_TD_STATUS_REG, count, 0);
i2c_release(FT5X06_BUS);
*count &= FT5X06_TD_STATUS_MASK;
if (*count > FT5X06_TOUCHES_COUNT_MAX) {
*count = 0;
}
return 0;
}
int ft5x06_read_touch_gesture(const ft5x06_t *dev, ft5x06_touch_gesture_t *gesture)
{
uint8_t gesture_id = 0;
i2c_acquire(FT5X06_BUS);
i2c_read_reg(FT5X06_BUS, FT5X06_ADDR, FT5X06_GESTURE_ID_REG, &gesture_id, 0);
i2c_release(FT5X06_BUS);
DEBUG("[ft5x06] read gesture_id '0x%02X'\n", gesture_id);
switch (gesture_id) {
case FT5X06_GESTURE_ID_MOVE_UP:
*gesture = FT5X06_TOUCH_MOVE_UP;
break;
case FT5X06_GESTURE_ID_MOVE_LEFT:
*gesture = FT5X06_TOUCH_MOVE_LEFT;
break;
case FT5X06_GESTURE_ID_MOVE_DOWN:
*gesture = FT5X06_TOUCH_MOVE_DOWN;
break;
case FT5X06_GESTURE_ID_MOVE_RIGHT:
*gesture = FT5X06_TOUCH_MOVE_RIGHT;
break;
case FT5X06_GESTURE_ID_ZOOM_IN:
*gesture = FT5X06_TOUCH_ZOOM_IN;
break;
case FT5X06_GESTURE_ID_ZOOM_OUT:
*gesture = FT5X06_TOUCH_ZOOM_OUT;
break;
default: /* Fallback to None */
*gesture = FT5X06_TOUCH_NO_GESTURE;
break;
}
return 0;
}

View File

@ -0,0 +1,133 @@
/*
* Copyright (C) 2021 Inria
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_ft5x06
* @{
*
* @file
* @brief Internal register addresses, bitfields and constants
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*/
#ifndef FT5X06_CONSTANTS_H
#define FT5X06_CONSTANTS_H
#include "kernel_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Constants (depends on variants)
* @{
*/
#define FT5X06_I2C_DEFAULT_ADDRESS (0x38)
#if IS_USED(MODULE_FT6X06) || IS_USED(MODULE_FT6X36)
#define FT5X06_VENDOR_ID (0xcd)
#else
#define FT5X06_VENDOR_ID (0x51)
#endif
#if IS_USED(MODULE_FT6X06) || IS_USED(MODULE_FT6X36)
#define FT5X06_TOUCHES_COUNT_MAX (2)
#else
#define FT5X06_TOUCHES_COUNT_MAX (5)
#endif
#if IS_USED(MODULE_FT6X06) || IS_USED(MODULE_FT6X36) || IS_USED(MODULE_FT5336) || \
IS_USED(MODULE_FT3316) || IS_USED(MODULE_FT5436I) || IS_USED(MODULE_FT5336I) || \
IS_USED(MODULE_FT5X46)
#define FT5X06_AUTO_CALIB_NEEDED 0
#else
#define FT5X06_AUTO_CALIB_NEEDED 1
#endif
/** @} */
/**
* @name Register addresses
* @{
*/
#define FT5X06_DEVIDE_MODE_REG (0x00)
#define FT5X06_GESTURE_ID_REG (0x01)
#define FT5X06_TD_STATUS_REG (0x02)
#define FT5X06_TOUCH1_XH_REG (0x03)
#define FT5X06_TOUCH1_XL_REG (0x04)
#define FT5X06_TOUCH1_YH_REG (0x05)
#define FT5X06_TOUCH1_YL_REG (0x06)
#define FT5X06_TOUCH2_XH_REG (0x09)
#define FT5X06_TOUCH2_XL_REG (0x0A)
#define FT5X06_TOUCH2_YH_REG (0x0B)
#define FT5X06_TOUCH2_YL_REG (0x0C)
#define FT5X06_TOUCH3_XH_REG (0x0F)
#define FT5X06_TOUCH3_XL_REG (0x11)
#define FT5X06_TOUCH3_YH_REG (0x12)
#define FT5X06_TOUCH3_YL_REG (0x13)
#define FT5X06_TOUCH4_XH_REG (0x15)
#define FT5X06_TOUCH4_XL_REG (0x16)
#define FT5X06_TOUCH4_YH_REG (0x17)
#define FT5X06_TOUCH4_YL_REG (0x18)
#define FT5X06_TOUCH5_XH_REG (0x1B)
#define FT5X06_TOUCH5_XL_REG (0x1C)
#define FT5X06_TOUCH5_YH_REG (0x1D)
#define FT5X06_TOUCH5_YL_REG (0x1E)
#define FT5X06_G_AUTO_CLB_MODE_REG (0xA0)
#define FT5X06_G_CIPHER_REG (0xA1)
#define FT5X06_G_LIB_VERSION_H_REG (0xA2)
#define FT5X06_G_LIB_VERSION_L_REG (0xA3)
#define FT5X06_G_MODE_REG (0xA4)
#define FT5X06_G_PMODE_REG (0xA5)
#define FT5X06_G_FIRMID_REG (0xA6)
#define FT5X06_G_STATE_REG (0xA7)
#define FT5X06_G_VENDOR_ID_REG (0xA8)
/** @} */
/**
* @name Gesture ID register bitfields
* @{
*/
#define FT5X06_GESTURE_ID_MOVE_UP (0x10)
#define FT5X06_GESTURE_ID_MOVE_LEFT (0x14)
#define FT5X06_GESTURE_ID_MOVE_DOWN (0x18)
#define FT5X06_GESTURE_ID_MOVE_RIGHT (0x1C)
#define FT5X06_GESTURE_ID_ZOOM_IN (0x48)
#define FT5X06_GESTURE_ID_ZOOM_OUT (0x49)
#define FT5X06_GESTURE_ID_NONE (0x00)
/** @} */
/**
* @name Touch detect status register bitfields
* @{
*/
#define FT5X06_TD_STATUS_MASK (0x0F)
/** @} */
/**
* @name Touch position (LSB/MSB) registers masks
* @{
*/
#define FT5X06_TOUCH_POS_LSB_MASK (0xFF)
#define FT5X06_TOUCH_POS_MSB_MASK (0x0F)
/** @} */
/**
* @name Interrupt mode register masks and bitfields
* @{
*/
#define FT5X06_G_MODE_INTERRUPT_MASK (0x03)
#define FT5X06_G_MODE_INTERRUPT_SHIFT (0x00)
#define FT5X06_G_MODE_INTERRUPT_POLLING (0x00)
#define FT5X06_G_MODE_INTERRUPT_TRIGGER (0x01)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* FT5X06_CONSTANTS_H */
/** @} */

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2021 Inria
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_ft5x06
*
* @{
* @file
* @brief Default configuration
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*/
#ifndef FT5X06_PARAMS_H
#define FT5X06_PARAMS_H
#include <stdint.h>
#include "board.h"
#include "ft5x06.h"
#include "ft5x06_constants.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Set default configuration parameters
* @{
*/
/* I2C configuration */
#ifndef FT5X06_PARAM_I2C_DEV
#define FT5X06_PARAM_I2C_DEV I2C_DEV(0)
#endif
#ifndef FT5X06_PARAM_ADDR
#define FT5X06_PARAM_ADDR (FT5X06_I2C_DEFAULT_ADDRESS)
#endif
#ifndef FT5X06_PARAM_INT_PIN
#define FT5X06_PARAM_INT_PIN GPIO_UNDEF
#endif
#ifndef FT5X06_PARAM_XMAX
#define FT5X06_PARAM_XMAX (480U)
#endif
#ifndef FT5X06_PARAM_YMAX
#define FT5X06_PARAM_YMAX (272U)
#endif
#define FT5X06_PARAMS { \
.i2c = FT5X06_PARAM_I2C_DEV, \
.addr = FT5X06_PARAM_ADDR, \
.int_pin = FT5X06_PARAM_INT_PIN, \
.xmax = FT5X06_PARAM_XMAX, \
.ymax = FT5X06_PARAM_YMAX, \
}
/**@}*/
/**
* @brief Configuration struct
*/
static const ft5x06_params_t ft5x06_params[] =
{
FT5X06_PARAMS
};
/**
* @brief Default screen identifiers
*/
#ifndef FT5X06_PARAM_SCREEN_IDS
#define FT5X06_PARAM_SCREEN_IDS 0
#endif
/**
* @brief Configure screen identifiers
*/
static const uint8_t ft5x06_screen_ids[] =
{
FT5X06_PARAM_SCREEN_IDS,
};
#ifdef __cplusplus
}
#endif
#endif /* FT5X06_PARAMS_H */
/** @} */

145
drivers/include/ft5x06.h Normal file
View File

@ -0,0 +1,145 @@
/*
* Copyright (C) 2021 Inria
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup drivers_ft5x06 FocalTech FT5x06 touch panel driver
* @ingroup drivers_sensors
* @brief Multi-touch capacitive panel controller
*
* This driver should also support FT5x06FT5606FT5x16FT6x06Ft6x36
* FT5x06iFT5336FT3316FT5436iFT5336iFT5x46.
*
* @{
*
* @file
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*/
#ifndef FT5X06_H
#define FT5X06_H
#include <stdint.h>
#include "periph/gpio.h"
#include "periph/i2c.h"
#include "ft5x06_constants.h"
#ifdef MODULE_TOUCH_DEV
#include "touch_dev.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Touch position structure
*/
typedef struct {
uint16_t x; /**< X position */
uint16_t y; /**< Y position */
} ft5x06_touch_position_t;
/**
* @brief Touch gesture
*/
typedef enum {
FT5X06_TOUCH_NO_GESTURE, /**< No gesture detected */
FT5X06_TOUCH_MOVE_UP, /**< Move up gesture detected */
FT5X06_TOUCH_MOVE_LEFT, /**< Move left gesture detected */
FT5X06_TOUCH_MOVE_DOWN, /**< Move down gesture detected */
FT5X06_TOUCH_MOVE_RIGHT, /**< Move right gesture detected */
FT5X06_TOUCH_ZOOM_IN, /**< Zoom int gesture detected */
FT5X06_TOUCH_ZOOM_OUT, /**< Zoom out gesture detected */
} ft5x06_touch_gesture_t;
/**
* @brief Signature of the touch event callback triggered from interrupt
*
* @param[in] arg optional context for the callback
*/
typedef void (*ft5x06_event_cb_t)(void *arg);
/**
* @brief Device initialization parameters
*/
typedef struct {
i2c_t i2c; /**< I2C device which is used */
uint8_t addr; /**< Device I2C address */
gpio_t int_pin; /**< Touch screen interrupt pin */
uint16_t xmax; /**< Touch screen max X position */
uint16_t ymax; /**< Touch screen max Y position */
} ft5x06_params_t;
/**
* @brief Device descriptor for the driver
*/
typedef struct {
#ifdef MODULE_TOUCH_DEV
touch_dev_t *dev; /**< Pointer to the generic touch device */
#endif
ft5x06_params_t params; /**< Initialization parameters */
} ft5x06_t;
/**
* @brief Initialize the given device
*
* @param[inout] dev Device descriptor of the driver
* @param[in] params Initialization parameters
* @param[in] cb Callback function called on touch interrupts
* @param[in] arg Context argument used in callback function
*
* @return 0 on success
* @return -ENODEV when no valid device
* @return -EPROTO on any bus error
*/
int ft5x06_init(ft5x06_t *dev, const ft5x06_params_t *params,
ft5x06_event_cb_t cb, void *arg);
/**
* @brief Read the touch positions
*
* @param[in] dev Device descriptor of the FT5x06
* @param[out] positions Touch positions
* @param[in] len Number of touch positions to read
*
* @return 0 on success
* @return -EPROTO on any bus error
*/
int ft5x06_read_touch_positions(const ft5x06_t *dev, ft5x06_touch_position_t *positions, size_t len);
/**
* @brief Read the number of touch
*
* @param[in] dev Device descriptor of the FT5x06
* @param[out] count Number of touch detected
*
* @return 0 on success
* @return -EPROTO on any bus error
*/
int ft5x06_read_touch_count(const ft5x06_t *dev, uint8_t *count);
/**
* @brief Read the gesture detected
*
* @param[in] dev Device descriptor of the FT5X06
* @param[out] gesture Gesture ID
*
* @return 0 on success
* @return -EPROTO on any bus error
*/
int ft5x06_read_touch_gesture(const ft5x06_t *dev, ft5x06_touch_gesture_t *gesture);
#ifdef __cplusplus
}
#endif
#endif /* FT5X06_H */
/** @} */