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

drivers/stmpe811: add implementation

This commit is contained in:
Alexandre Abadie 2019-04-28 17:54:09 +02:00
parent 3141e91380
commit 1bc842707a
No known key found for this signature in database
GPG Key ID: 1C919A403CAE1405
7 changed files with 721 additions and 0 deletions

View File

@ -576,6 +576,12 @@ ifneq (,$(filter si70%,$(USEMODULE)))
USEMODULE += si70xx
endif
ifneq (,$(filter stmpe811,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio_irq
FEATURES_REQUIRED += periph_i2c
USEMODULE += xtimer
endif
ifneq (,$(filter slipdev,$(USEMODULE)))
USEMODULE += tsrb
FEATURES_REQUIRED += periph_uart

View File

@ -308,6 +308,10 @@ ifneq (,$(filter srf04,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/srf04/include
endif
ifneq (,$(filter stmpe811,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/stmpe811/include
endif
ifneq (,$(filter sx127x,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/sx127x/include
endif

128
drivers/include/stmpe811.h Normal file
View File

@ -0,0 +1,128 @@
/*
* Copyright (C) 2019 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_stmpe811 STMPE811 Touchscreen Controller
* @ingroup drivers_sensors
* @brief Device driver interface for the STMPE811 touchscreen controller
*
* @{
*
* @file
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*/
#ifndef STMPE811_H
#define STMPE811_H
#include "saul.h"
#include "periph/gpio.h"
#include "periph/i2c.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Return codes
*/
enum {
STMPE811_OK = 0, /**< Everything was fine */
STMPE811_ERR_I2C, /**< Error on the I2C bus */
STMPE811_ERR_NODEV, /**< No valid device on I2C bus */
STMPE811_ERR_RESET, /**< Software reset failed */
};
/**
* @brief Touch state enum
*/
typedef enum {
STMPE811_TOUCH_STATE_PRESSED, /**< Touchscreen is pressed */
STMPE811_TOUCH_STATE_RELEASED, /**< Touchscreen is released */
} stmpe811_touch_state_t;
/**
* @brief Touch position structure
*/
typedef struct {
uint16_t x; /**< X position */
uint16_t y; /**< Y position */
} stmpe811_touch_position_t;
/**
* @brief Signature of touch event callback triggered from interrupt
*
* @param[in] arg optional context for the callback
*/
typedef void (*touch_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 */
} stmpe811_params_t;
/**
* @brief Device descriptor for the STMPE811 sensor
*/
typedef struct {
stmpe811_params_t params; /**< Device parameters */
uint16_t prev_x; /**< Previous X coordinate */
uint16_t prev_y; /**< Previous Y coordinate */
} stmpe811_t;
/**
* @brief Initialize the given STMPE811 device
*
* @param[inout] dev Device descriptor of the STMPE811
* @param[in] params Initialization parameters of the STMPE811 device
* @param[in] cb Callback function called on touch interrupts
* @param[in] arg Context argument used in callback function
*
* @return STMPE811_OK on success
* @return -STMPE811_ERR_NODEV when no valid device
* @return -STMPE811_ERR_RESET when software reset failed
* @return -STMPE811_ERR_I2C on any I2C error
*/
int stmpe811_init(stmpe811_t *dev, const stmpe811_params_t * params,
touch_event_cb_t cb, void *arg);
/**
* @brief Read the touch position
*
* @param[in] dev Device descriptor of the STMPE811
* @param[out] position Touch position
*
* @return STMPE811_OK on success
* @return -STMPE811_ERR_I2C on any I2C error
*/
int stmpe811_read_touch_position(stmpe811_t *dev, stmpe811_touch_position_t *position);
/**
* @brief Read the touch state (pressed or released)
*
* @param[in] dev Device descriptor of the STMPE811
* @param[out] state Touch state
*
* @return STMPE811_OK on success
* @return -STMPE811_ERR_I2C on any I2C error
*/
int stmpe811_read_touch_state(const stmpe811_t *dev, stmpe811_touch_state_t *state);
#ifdef __cplusplus
}
#endif
#endif /* STMPE811_H */
/** @} */

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,229 @@
/*
* Copyright (C) 2019 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_stmpe811
*
* @{
* @file
* @brief Constants for STMPE811
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*/
#ifndef STMPE811_CONSTANTS_H
#define STMPE811_CONSTANTS_H
#include "stmpe811.h"
#ifdef __cplusplus
extern "C" {
#endif
#define STMPE811_I2C_ADDR_DEFAULT (0x41) /**< Default I2C address */
#define STMPE811_CHIP_ID_VALUE (0x0811) /**< Chip ID */
/* @name Registers
* @{
*/
#define STMPE811_CHIP_ID (0x00) /**< STMPE811 Device identification */
#define STMPE811_ID_VER (0x02) /**< STMPE811 Revision number */
#define STMPE811_SYS_CTRL1 (0x03) /**< Reset control */
#define STMPE811_SYS_CTRL2 (0x04) /**< Clock control */
#define STMPE811_SPI_CFG (0x08) /**< SPI interface configuration */
#define STMPE811_INT_CTRL (0x09) /**< Interrupt control register */
#define STMPE811_INT_EN (0x0A) /**< Interrupt enable register */
#define STMPE811_INT_STA (0x0B) /**< Interrupt status register */
#define STMPE811_GPIO_EN (0x0C) /**< GPIO interrupt enable register */
#define STMPE811_GPIO_INT_STA (0x0D) /**< GPIO interrupt status register */
#define STMPE811_ADC_INT_EN (0x0E) /**< ADC interrupt enable register */
#define STMPE811_ADC_INT_STA (0x0F) /**< ADC interface status register */
#define STMPE811_GPIO_SET_PIN (0x10) /**< GPIO set pin register */
#define STMPE811_GPIO_CLR_PIN (0x11) /**< GPIO clear pin register */
#define STMPE811_MP_STA (0x12) /**< GPIO monitor pin state register */
#define STMPE811_GPIO_DIR (0x13) /**< GPIO direction register */
#define STMPE811_GPIO_ED (0x14) /**< GPIO edge detect register */
#define STMPE811_GPIO_RE (0x15) /**< GPIO rising edge register */
#define STMPE811_GPIO_FE (0x16) /**< GPIO falling edge register */
#define STMPE811_GPIO_ALT_FUNCTION (0x17) /**< Alternate function register */
#define STMPE811_ADC_CTRL1 (0x20) /**< ADC control */
#define STMPE811_ADC_CTRL2 (0x21) /**< ADC control */
#define STMPE811_ADC_CAPT (0x22) /**< To initiate ADC data acquisition */
#define STMPE811_ADC_DATA_CHO (0x30) /**< ADC channel 0 */
#define STMPE811_ADC_DATA_CH1 (0x32) /**< ADC channel 1 */
#define STMPE811_ADC_DATA_CH2 (0x34) /**< ADC channel 2 */
#define STMPE811_ADC_DATA_CH3 (0x36) /**< ADC channel 3 */
#define STMPE811_ADC_DATA_CH4 (0x38) /**< ADC channel 4 */
#define STMPE811_ADC_DATA_CH5 (0x3A) /**< ADC channel 5 */
#define STMPE811_ADC_DATA_CH6 (0x3C) /**< ADC channel 6 */
#define STMPE811_ADC_DATA_CH7 (0x3E) /**< ADC channel 7 */
#define STMPE811_TSC_CTRL (0x40) /**< 4-wire tsc setup */
#define STMPE811_TSC_CFG (0x41) /**< Tsc configuration */
#define STMPE811_WDW_TR_X (0x42) /**< Window setup for top right X */
#define STMPE811_WDW_TR_Y (0x44) /**< Window setup for top right Y */
#define STMPE811_WDW_BL_X (0x46) /**< Window setup for bottom left X */
#define STMPE811_WDW_BL_Y (0x48) /**< Window setup for bottom left Y */
#define STMPE811_FIFO_TH (0x4A) /**< FIFO level to generate interrupt */
#define STMPE811_FIFO_CTRL_STA (0x4B) /**< Current status of FIFO */
#define STMPE811_FIFO_SIZE (0x4C) /**< Current filled level of FIFO */
#define STMPE811_TSC_DATA_X (0x4D) /**< Data port for tsc data access */
#define STMPE811_TSC_DATA_Y (0x4F) /**< Data port for tsc data access */
#define STMPE811_TSC_DATA_Z (0x51) /**< Data port for tsc data access */
#define STMPE811_TSC_DATA_XYZ (0x52) /**< Data port for tsc data access */
#define STMPE811_TSC_DATA_INC (0x57) /**< Data port for tsc auto-increment data access */
#define STMPE811_TSC_DATA_NON_INC (0xD7) /**< Data port for tsc non auto-increment data access */
#define STMPE811_TSC_FRACTION_Z (0x56) /**< Touchscreen controller FRACTION_Z */
#define STMPE811_TSC_DATA (0x57) /**< Data port for tsc data access */
#define STMPE811_TSC_I_DRIVE (0x58) /**< Touchscreen controller drivel */
#define STMPE811_TSC_SHIELD (0x59) /**< Touchscreen controller shield */
#define STMPE811_TEMP_CTRL (0x60) /**< Temperature sensor setup */
#define STMPE811_TEMP_DATA (0x61) /**< Temperature data access port */
#define STMPE811_TEMP_TH (0x62) /**< Threshold for temp controlled int */
/** @} */
/* @name SYS_CTRL1 register bitfields
* @{
*/
#define STMPE811_SYS_CTRL1_HIBERNATE (1 << 0) /**< Hibernate the device*/
#define STMPE811_SYS_CTRL1_SOFT_RESET (1 << 1) /**< Trigger software reset */
/** @} */
/* @name SYS_CTRL2 register bitfields
* @{
*/
#define STMPE811_SYS_CTRL2_ADC_OFF (1 << 0) /**< Disable ADC */
#define STMPE811_SYS_CTRL2_TSC_OFF (1 << 1) /**< Disable Touchscreen*/
#define STMPE811_SYS_CTRL2_GPIO_OFF (1 << 2) /**< Disable GPIO */
#define STMPE811_SYS_CTRL2_TS_OFF (1 << 3) /**< Disable Temperature sensor */
/** @} */
/* @name INT_CTRL register bitfields
* @{
*/
#define STMPE811_INT_CTRL_INT_POLARITY (1 << 2) /**< Configure interrupt polarity (falling or raising) */
#define STMPE811_INT_CTRL_INT_TYPE (1 << 1) /**< Configure interrupt type (edge or level) */
#define STMPE811_INT_CTRL_GLOBAL_INT (1 << 0) /**< Enable global interrupt */
/** @} */
/* @name INT_EN register bitfields
* @{
*/
#define STMPE811_INT_EN_TOUCH_DET (1 << 0) /**< Enable touch detection interrupt */
#define STMPE811_INT_EN_FIFO_TH (1 << 1) /**< Enable FIFO threshold interrupt */
#define STMPE811_INT_EN_FIFO_OFLOW (1 << 2) /**< Enable FIFO overflow interrupt */
#define STMPE811_INT_EN_FIFO_FULL (1 << 3) /**< Enable FIFO full interrupt */
#define STMPE811_INT_EN_FIFO_EMPTY (1 << 4) /**< Enable FIFO empty interrupt */
#define STMPE811_INT_EN_TEMP_SENS (1 << 5) /**< Enable temperature sensor interrupt */
#define STMPE811_INT_EN_ADC (1 << 6) /**< Enable ADC interrupt */
#define STMPE811_INT_EN_GPIO (1 << 7) /**< Enable GPIO interrupt */
/** @} */
/* @name ADC_CTRL1 register bitfields
* @{
*/
#define STMPE811_ADC_CTRL1_SAMPLE_TIME_POS (4) /**< Sample time bits shift position */
#define STMPE811_ADC_CTRL1_SAMPLE_TIME_36 (0b000) /**< Conversion time: 36 cycles */
#define STMPE811_ADC_CTRL1_SAMPLE_TIME_44 (0b001) /**< Conversion time: 44 cycles */
#define STMPE811_ADC_CTRL1_SAMPLE_TIME_56 (0b010) /**< Conversion time: 56 cycles */
#define STMPE811_ADC_CTRL1_SAMPLE_TIME_64 (0b011) /**< Conversion time: 64 cycles */
#define STMPE811_ADC_CTRL1_SAMPLE_TIME_80 (0b100) /**< Conversion time: 80 cycles */
#define STMPE811_ADC_CTRL1_SAMPLE_TIME_96 (0b101) /**< Conversion time: 96 cycles */
#define STMPE811_ADC_CTRL1_SAMPLE_TIME_124 (0b110) /**< Conversion time: 124 cycles */
#define STMPE811_ADC_CTRL1_MOD_12B (1 << 3) /**< Enable 12 bit ADC (10bit if 0) */
/** @} */
/* @name ADC_CTRL2 register bitfields
* @{
*/
#define STMPE811_ADC_CTRL2_FREQ_1_625MHZ (0b00) /**< ADC clock frequency 1.625MHz */
#define STMPE811_ADC_CTRL2_FREQ_3_25MHZ (0b01) /**< ADC clock frequency 3.25MHz */
#define STMPE811_ADC_CTRL2_FREQ_6_5MHZ (0b10) /**< ADC clock frequency 6.5MHz */
#define STMPE811_ADC_CTRL2_FREQ_6_5_2MHZ (0b11) /**< ADC clock frequency 6.5MHz */
/** @} */
/* @name TSC_CTRL register bitfields
* @{
*/
#define STMPE811_TSC_CTRL_EN (1 << 0) /**< Enable touchscreen */
#define STMPE811_TSC_CTRL_OPMOD_POS (1) /**< Operating mode bit shift position */
#define STMPE811_TSC_CTRL_OPMOD_XYZ (0b000) /**< X,Y,Z acquisition */
#define STMPE811_TSC_CTRL_OPMOD_XY_ONLY (0b001) /**< X,Y only acquisition */
#define STMPE811_TSC_CTRL_OPMOD_X_ONLY (0b010) /**< X only acquisition */
#define STMPE811_TSC_CTRL_OPMOD_Y_ONLY (0b011) /**< Y only acquisition */
#define STMPE811_TSC_CTRL_OPMOD_Z_ONLY (0b100) /**< Z only acquisition */
#define STMPE811_TSC_CTRL_TRACK_POS (4) /**< Movement tracking index bit shift position */
#define STMPE811_TSC_CTRL_TRACK_NO (0b000) /**< No window tracking */
#define STMPE811_TSC_CTRL_TRACK_4 (0b001) /**< Tracking index 4 */
#define STMPE811_TSC_CTRL_TRACK_8 (0b010) /**< Tracking index 8 */
#define STMPE811_TSC_CTRL_TRACK_16 (0b011) /**< Tracking index 16 */
#define STMPE811_TSC_CTRL_TRACK_32 (0b100) /**< Tracking index 32 */
#define STMPE811_TSC_CTRL_TRACK_64 (0b101) /**< Tracking index 64 */
#define STMPE811_TSC_CTRL_TRACK_92 (0b110) /**< Tracking index 92 */
#define STMPE811_TSC_CTRL_TRACK_127 (0b111) /**< Tracking index 127 */
#define STMPE811_TSC_CTRL_STA (1 << 7) /**< Touchscreen status (1: touch detected, 0: no touch detected), read-only */
/** @} */
/* @name TSC_CFG register bitfields
* @{
*/
#define STMPE811_TSC_CFG_AVE_CTRL_POS (6) /**< Average control bit shift position */
#define STMPE811_TSC_CFG_AVE_CTRL_1 (0b00) /**< Average control, 1 sample */
#define STMPE811_TSC_CFG_AVE_CTRL_2 (0b01) /**< Average control, 2 sample */
#define STMPE811_TSC_CFG_AVE_CTRL_4 (0b10) /**< Average control, 4 sample */
#define STMPE811_TSC_CFG_AVE_CTRL_8 (0b11) /**< Average control, 8 sample */
#define STMPE811_TSC_CFG_TOUCH_DET_DELAY_POS (3) /**< Touch detection delay bit shift position */
#define STMPE811_TSC_CFG_TOUCH_DET_DELAY_10US (0b000) /**< Touch detection 10us delay */
#define STMPE811_TSC_CFG_TOUCH_DET_DELAY_50US (0b001) /**< Touch detection 50us delay */
#define STMPE811_TSC_CFG_TOUCH_DET_DELAY_100US (0b010) /**< Touch detection 100us delay */
#define STMPE811_TSC_CFG_TOUCH_DET_DELAY_500US (0b011) /**< Touch detection 500us delay */
#define STMPE811_TSC_CFG_TOUCH_DET_DELAY_1MS (0b100) /**< Touch detection 1ms delay */
#define STMPE811_TSC_CFG_TOUCH_DET_DELAY_5MS (0b101) /**< Touch detection 5ms delay */
#define STMPE811_TSC_CFG_TOUCH_DET_DELAY_10MS (0b110) /**< Touch detection 10ms delay */
#define STMPE811_TSC_CFG_TOUCH_DET_DELAY_50MS (0b111) /**< Touch detection 50ms delay */
#define STMPE811_TSC_CFG_SETTLING_10US (0b000) /**< Settling time 10us */
#define STMPE811_TSC_CFG_SETTLING_100US (0b001) /**< Settling time 100us */
#define STMPE811_TSC_CFG_SETTLING_500US (0b010) /**< Settling time 500us */
#define STMPE811_TSC_CFG_SETTLING_1MS (0b011) /**< Settling time 1ms */
#define STMPE811_TSC_CFG_SETTLING_5MS (0b100) /**< Settling time 5ms */
#define STMPE811_TSC_CFG_SETTLING_10MS (0b101) /**< Settling time 10ms */
#define STMPE811_TSC_CFG_SETTLING_50MS (0b110) /**< Settling time 50ms */
#define STMPE811_TSC_CFG_SETTLING_100MS (0b111) /**< Settling time 100ms */
/** @} */
/* @name FIFO_CTRL_STA register bitfields
* @{
*/
#define STMPE811_FIFO_CTRL_STA_RESET (1 << 0) /**< Reset FIFO */
/** @} */
/* @name TSC_FRACTION_Z register bitfields
* @{
*/
#define STMPE811_TSC_FRACTION_Z_0_8 (0b000) /**< Fractional part is 0, whole part is 8 */
#define STMPE811_TSC_FRACTION_Z_1_7 (0b001) /**< Fractional part is 1, whole part is 7 */
#define STMPE811_TSC_FRACTION_Z_2_6 (0b010) /**< Fractional part is 2, whole part is 6 */
#define STMPE811_TSC_FRACTION_Z_3_5 (0b011) /**< Fractional part is 3, whole part is 5 */
#define STMPE811_TSC_FRACTION_Z_4_4 (0b100) /**< Fractional part is 4, whole part is 4 */
#define STMPE811_TSC_FRACTION_Z_5_3 (0b101) /**< Fractional part is 5, whole part is 3 */
#define STMPE811_TSC_FRACTION_Z_6_2 (0b110) /**< Fractional part is 6, whole part is 2 */
#define STMPE811_TSC_FRACTION_Z_7_1 (0b111) /**< Fractional part is 7, whole part is 1 */
/** @} */
/* @name TSC_I_DRIVE register bitfields
* @{
*/
#define STMPE811_TSC_I_DRIVE_50MA (1 << 0) /**< Enable 50mA drive current, 20mA if 0 */
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* STMPE811_CONSTANTS_H */
/** @} */

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2019 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_stmpe811
*
* @{
* @file
* @brief Default configuration for STMPE811
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*/
#ifndef STMPE811_PARAMS_H
#define STMPE811_PARAMS_H
#include "board.h"
#include "stmpe811.h"
#include "stmpe811_constants.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Set default configuration parameters for the STMPE811
* @{
*
* These default values are adapted for the @ref boards_stm32f429i-disc1 board
*/
#ifndef STMPE811_PARAM_I2C_DEV
#define STMPE811_PARAM_I2C_DEV I2C_DEV(0)
#endif
#ifndef STMPE811_PARAM_ADDR
#define STMPE811_PARAM_ADDR (STMPE811_I2C_ADDR_DEFAULT)
#endif
#ifndef STMPE811_PARAM_INT_PIN
#define STMPE811_PARAM_INT_PIN GPIO_PIN(0, 15)
#endif
#ifndef STMPE811_PARAM_XMAX
#define STMPE811_PARAM_XMAX (240U)
#endif
#ifndef STMPE811_PARAM_YMAX
#define STMPE811_PARAM_YMAX (320U)
#endif
#ifndef STMPE811_PARAMS
#define STMPE811_PARAMS { .i2c = STMPE811_PARAM_I2C_DEV, \
.addr = STMPE811_PARAM_ADDR, \
.int_pin = STMPE811_PARAM_INT_PIN, \
.xmax = STMPE811_PARAM_XMAX, \
.ymax = STMPE811_PARAM_YMAX, \
}
#endif
/**@}*/
/**
* @brief Configure STMPE811
*/
static const stmpe811_params_t stmpe811_params[] =
{
STMPE811_PARAMS
};
#ifdef __cplusplus
}
#endif
#endif /* STMPE811_PARAMS_H */
/** @} */

278
drivers/stmpe811/stmpe811.c Normal file
View File

@ -0,0 +1,278 @@
/*
* Copyright (C) 2019 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_stmpe811
* @{
*
* @file
* @brief Device driver implementation for the STMPE811 touchscreen controller.
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*
* @}
*/
#include <inttypes.h>
#include "xtimer.h"
#include "periph/i2c.h"
#include "periph/gpio.h"
#include "stmpe811.h"
#include "stmpe811_constants.h"
#include "stmpe811_params.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define STMPE811_DEV_I2C (dev->params.i2c)
#define STMPE811_DEV_ADDR (dev->params.addr)
static int _soft_reset(const stmpe811_t *dev)
{
if (i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_SYS_CTRL1, STMPE811_SYS_CTRL1_SOFT_RESET, 0) < 0) {
DEBUG("[stmpe811] soft reset: cannot write soft reset bit to SYS_CTRL1 register\n");
return -STMPE811_ERR_I2C;
}
xtimer_usleep(10 * US_PER_MS);
if (i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_SYS_CTRL1, 0, 0) < 0) {
DEBUG("[stmpe811] soft reset: cannot clear SYS_CTRL1 register\n");
return -STMPE811_ERR_I2C;
}
xtimer_usleep(2 * US_PER_MS);
return STMPE811_OK;
}
static void _reset_fifo(const stmpe811_t *dev)
{
i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_FIFO_CTRL_STA, STMPE811_FIFO_CTRL_STA_RESET, 0);
i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_FIFO_CTRL_STA, 0, 0);
}
static void _clear_interrupt_status(const stmpe811_t *dev)
{
i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR, STMPE811_INT_STA, 0xff, 0);
}
int stmpe811_init(stmpe811_t *dev, const stmpe811_params_t * params, touch_event_cb_t cb, void *arg)
{
dev->params = *params;
int ret = STMPE811_OK;
/* Acquire I2C device */
i2c_acquire(STMPE811_DEV_I2C);
uint16_t device_id;
if (i2c_read_regs(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_CHIP_ID, &device_id, 2, 0) < 0) {
DEBUG("[stmpe811] init: cannot read CHIP_ID register\n");
i2c_release(STMPE811_DEV_I2C);
return -STMPE811_ERR_I2C;
}
device_id = (device_id << 8) | (device_id >> 8);
if (device_id != STMPE811_CHIP_ID_VALUE) {
DEBUG("[stmpe811] init: invalid device id (actual: 0x%04X, expected: 0x%04X)\n",
device_id, STMPE811_CHIP_ID_VALUE);
i2c_release(STMPE811_DEV_I2C);
return -STMPE811_ERR_NODEV;
}
DEBUG("[stmpe811] init: valid device\n");
ret = _soft_reset(dev);
if (ret != STMPE811_OK) {
DEBUG("[stmpe811] init: reset failed\n");
i2c_release(STMPE811_DEV_I2C);
return -STMPE811_ERR_RESET;
}
DEBUG("[stmpe811] init: soft reset done\n");
/* Initialization sequence */
/* disable temperature sensor and GPIO */
ret = i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_SYS_CTRL2,
(STMPE811_SYS_CTRL2_TS_OFF | STMPE811_SYS_CTRL2_GPIO_OFF), 0);
/* set to 80 cycles and adc resolution to 12 bit*/
uint8_t reg = ((uint8_t)(STMPE811_ADC_CTRL1_SAMPLE_TIME_80 << STMPE811_ADC_CTRL1_SAMPLE_TIME_POS) |
STMPE811_ADC_CTRL1_MOD_12B);
ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_ADC_CTRL1, reg, 0);
/* set adc clock speed to 3.25 MHz */
ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_ADC_CTRL2, STMPE811_ADC_CTRL2_FREQ_3_25MHZ, 0);
/* set GPIO AF to function as ts/adc */
ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_GPIO_ALT_FUNCTION, 0x00, 0);
/* set touchscreen configuration */
reg = ((uint8_t)(STMPE811_TSC_CFG_AVE_CTRL_4 << STMPE811_TSC_CFG_AVE_CTRL_POS) |
(uint8_t)(STMPE811_TSC_CFG_TOUCH_DET_DELAY_500US << STMPE811_TSC_CFG_TOUCH_DET_DELAY_POS) |
(STMPE811_TSC_CFG_SETTLING_500US));
ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_TSC_CFG, reg, 0);
/* set fifo threshold */
ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_FIFO_TH, 0x01, 0);
/* reset fifo */
_reset_fifo(dev);
/* set fractional part to 7, whole part to 1 */
ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_TSC_FRACTION_Z, STMPE811_TSC_FRACTION_Z_7_1, 0);
/* set current limit value to 50 mA */
ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_TSC_I_DRIVE, STMPE811_TSC_I_DRIVE_50MA, 0);
/* enable touchscreen clock */
ret += i2c_read_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_SYS_CTRL2, &reg, 0);
reg &= ~STMPE811_SYS_CTRL2_TSC_OFF;
ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_SYS_CTRL2, reg, 0);
ret += i2c_read_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_TSC_CTRL, &reg, 0);
reg |= STMPE811_TSC_CTRL_EN;
ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_TSC_CTRL, reg, 0);
/* clear interrupt status */
_clear_interrupt_status(dev);
if ((dev->params.int_pin != GPIO_UNDEF) && cb) {
DEBUG("[stmpe811] init: configuring touchscreen interrupt\n");
gpio_init_int(dev->params.int_pin, GPIO_IN, GPIO_RISING, cb, arg);
/* Enable touchscreen interrupt */
ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_INT_EN, STMPE811_INT_EN_TOUCH_DET, 0);
/* Enable global interrupt */
ret += i2c_write_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_INT_CTRL, STMPE811_INT_CTRL_GLOBAL_INT, 0);
}
if (ret < 0) {
i2c_release(STMPE811_DEV_I2C);
DEBUG("[stmpe811] init: initialization sequence failed\n");
return -STMPE811_ERR_I2C;
}
/* Release I2C device */
i2c_release(STMPE811_DEV_I2C);
DEBUG("[stmpe811] initialization successful\n");
return ret;
}
int stmpe811_read_touch_position(stmpe811_t *dev, stmpe811_touch_position_t *position)
{
uint16_t tmp_x, tmp_y;
/* Acquire I2C device */
i2c_acquire(STMPE811_DEV_I2C);
uint8_t xyz[4];
uint32_t xyz_ul;
if (i2c_read_regs(STMPE811_DEV_I2C, STMPE811_DEV_ADDR,
STMPE811_TSC_DATA_NON_INC, &xyz, sizeof(xyz), 0) < 0) {
DEBUG("[stmpe811] position: cannot read position\n");
i2c_release(STMPE811_DEV_I2C);
return -STMPE811_ERR_I2C;
}
_reset_fifo(dev);
/* Release I2C device */
i2c_release(STMPE811_DEV_I2C);
xyz_ul = ((uint32_t)xyz[0] << 24) | ((uint32_t)xyz[1] << 16) | \
((uint32_t)xyz[2] << 8) | (xyz[3] << 0);
tmp_x = (xyz_ul >> 20) & 0xfff;
tmp_y = (xyz_ul >> 8) & 0xfff;
/* Y value first correction */
tmp_y -= 360;
/* Y value second correction */
tmp_y /= 11;
/* clamp y position */
if (tmp_y > dev->params.ymax) {
tmp_y = dev->prev_y;
}
/* X value first correction */
if (tmp_x <= 3000) {
tmp_x = 3870 - tmp_x;
}
else {
tmp_x = 3800 - tmp_x;
}
/* X value second correction */
tmp_x /= 15;
/* clamp x position */
if (tmp_x > dev->params.xmax) {
tmp_x = dev->prev_x;
}
dev->prev_x = tmp_x;
dev->prev_y = tmp_y;
position->x = tmp_x;
position->y = tmp_y;
return STMPE811_OK;
}
int stmpe811_read_touch_state(const stmpe811_t *dev, stmpe811_touch_state_t *state)
{
uint8_t val;
/* Acquire I2C device */
i2c_acquire(STMPE811_DEV_I2C);
if (i2c_read_reg(STMPE811_DEV_I2C, STMPE811_DEV_ADDR, STMPE811_TSC_CTRL, &val, 0) < 0) {
DEBUG("[stmpe811] position: cannot read touch state\n");
i2c_release(STMPE811_DEV_I2C);
return -STMPE811_ERR_I2C;
}
if ((val & STMPE811_TSC_CTRL_STA)) {
_clear_interrupt_status(dev);
*state = STMPE811_TOUCH_STATE_PRESSED;
}
else {
_reset_fifo(dev);
*state = STMPE811_TOUCH_STATE_RELEASED;
}
/* Release I2C device */
i2c_release(STMPE811_DEV_I2C);
return STMPE811_OK;
}