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

Merge pull request #13214 from bergzand/pr/cst816s/initial

cst816s: Initial include of cst816s touch screen driver
This commit is contained in:
Alexandre Abadie 2021-01-14 18:51:21 +01:00 committed by GitHub
commit 6e21c72382
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 470 additions and 0 deletions

View File

@ -100,6 +100,17 @@ extern mtd_dev_t *mtd0;
#define MTD_0 mtd0
/** @} */
/**
* @name Touch screen configuration
* @{
*/
#define CST816S_PARAM_I2C_DEV I2C_DEV(0)
#define CST816S_PARAM_I2C_ADDR (0x15)
#define CST816S_PARAM_IRQ GPIO_PIN(0, 28)
#define CST816S_PARAM_IRQ_FLANK GPIO_FALLING
#define CST816S_PARAM_RESET GPIO_PIN(0, 10)
/** @} */
#ifdef __cplusplus
}
#endif

1
drivers/cst816s/Makefile Normal file
View File

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

View File

@ -0,0 +1,3 @@
FEATURES_REQUIRED += periph_gpio_irq
FEATURES_REQUIRED += periph_i2c
USEMODULE += xtimer

View File

@ -0,0 +1,2 @@
USEMODULE_INCLUDES_cst816s := $(LAST_MAKEFILEDIR)/include
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_cst816s)

106
drivers/cst816s/cst816s.c Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2020 Koen Zandberg
*
* 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_cst816s
* @{
*
* @file
* @brief Device driver implementation for cst816s touch screen
*
* @author Koen Zandberg <koen@bergzand.net>
*
* @}
*/
#include "log.h"
#include "periph/gpio.h"
#include "periph/i2c.h"
#include "xtimer.h"
#include "cst816s.h"
#include "cst816s_internal.h"
#define ENABLE_DEBUG 0
#include "debug.h"
const char *cst816s_gesture_str[] = {
[CST816S_GESTURE_NONE] = "none",
[CST816S_GESTURE_SLIDE_DOWN] = "slide down",
[CST816S_GESTURE_SLIDE_UP] = "slide up",
[CST816S_GESTURE_SLIDE_LEFT] = "slide left",
[CST816S_GESTURE_SLIDE_RIGHT] = "slide right",
[CST816S_GESTURE_SINGLE_CLICK] = "single click",
[CST816S_GESTURE_DOUBLE_CLICK] = "double click",
[CST816S_GESTURE_LONG_PRESS] = "long press",
};
static void _gpio_irq(void *arg)
{
cst816s_t *dev = arg;
assert(dev);
if (dev->cb) {
dev->cb(dev->cb_arg);
}
}
static void _cst816s_reset(const cst816s_t *dev)
{
/* Reset, sleep durations based on
* https://github.com/lupyuen/hynitron_i2c_cst0xxse/blob/master/cst0xx_core.c#L1078-L1085 */
gpio_clear(dev->params->reset);
xtimer_usleep(CST816S_RESET_DURATION_LOW);
gpio_set(dev->params->reset);
xtimer_usleep(CST816S_RESET_DURATION_HIGH);
}
int cst816s_read(const cst816s_t *dev, cst816s_touch_data_t *data)
{
uint8_t buf[9]; /* 3 bytes "header" and 6 bytes touch info */
i2c_acquire(dev->params->i2c_dev);
int res = i2c_read_regs(dev->params->i2c_dev, dev->params->i2c_addr,
0, buf, sizeof(buf), 0);
i2c_release(dev->params->i2c_dev);
if (res < 0) {
return res;
}
data->gesture = buf[1];
data->action = buf[3] >> 6;
data->x = ((buf[3] & 0x0f) << 8) | buf[4];
data->y = ((buf[5] & 0x0f) << 8) | buf[6];
return 0;
}
int cst816s_init(cst816s_t *dev, const cst816s_params_t *params,
cst816s_irq_cb_t cb, void *arg)
{
assert(dev && params);
dev->params = params;
dev->cb = cb;
dev->cb_arg = arg;
if (dev->params->reset != GPIO_UNDEF) {
gpio_init(dev->params->reset, GPIO_OUT);
_cst816s_reset(dev);
}
if ((dev->params->irq != GPIO_UNDEF) && cb) {
if (gpio_init_int(dev->params->irq, GPIO_IN,
dev->params->irq_flank,
_gpio_irq, dev) < 0) {
return CST816S_ERR_IRQ;
}
}
return CST816S_OK;
/* The device will not respond until the first touch event */
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2020 Koen Zandberg
*
* 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_cst816s
*
* @{
* @file
* @brief Internal constants for cst816s
*
* @author Koen Zandberg <koen@bergzand.net>
*/
#ifndef CST816S_INTERNAL_H
#define CST816S_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name cst816s timing constants
* @{
*/
#define CST816S_RESET_DURATION_LOW (20 * US_PER_MS)
#define CST816S_RESET_DURATION_HIGH (400 * US_PER_MS)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* CST816S_INTERNAL_H */
/** @} */

View File

@ -0,0 +1,83 @@
/*
* Copyright (C) 2020 Koen Zandberg
*
* 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_cst816s
*
* @{
* @file
*
* @brief Default configuration for the CST816S touch screen driver
*
* @author Koen Zandberg <koen@bergzand.net>
*/
#ifndef CST816S_PARAMS_H
#define CST816S_PARAMS_H
#include "board.h"
#include "cst816s.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Set default configuration parameters for the CST816S
* @{
*/
/* I2C configuration */
#ifndef CST816S_PARAM_I2C_DEV
#define CST816S_PARAM_I2C_DEV I2C_DEV(0)
#endif
#ifndef CST816S_PARAM_I2C_ADDR
#define CST816S_PARAM_I2C_ADDR (0x15)
#endif
#ifndef CST816S_PARAM_IRQ
#define CST816S_PARAM_IRQ GPIO_PIN(0, 28)
#endif
#ifndef CST816S_PARAM_IRQ_FLANK
#define CST816S_PARAM_IRQ_FLANK GPIO_FALLING
#endif
#ifndef CST816S_PARAM_RESET
#define CST816S_PARAM_RESET GPIO_PIN(0, 10)
#endif
#define CST816S_PARAMS \
{ \
.i2c_dev = CST816S_PARAM_I2C_DEV, \
.i2c_addr = CST816S_PARAM_I2C_ADDR, \
.irq = CST816S_PARAM_IRQ, \
.irq_flank = CST816S_PARAM_IRQ_FLANK, \
.reset = CST816S_PARAM_RESET, \
}
/**@}*/
/**
* @brief Configure CST816S
*/
static const cst816s_params_t cst816s_params[] =
{
CST816S_PARAMS
};
/**
* @brief The number of configured sensors
*/
#define CST816S_NUMOF ARRAY_SIZE(cst816s_params)
#ifdef __cplusplus
}
#endif
#endif /* CST816S_PARAMS_H */
/** @} */

154
drivers/include/cst816s.h Normal file
View File

@ -0,0 +1,154 @@
/*
* Copyright (C) 2020 Koen Zandberg
*
* 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_cst816s Cst816S touch screen driver
*
* @ingroup drivers_sensors
* @brief Device driver interface for the Hynitron CST816S touch screen
*
* The CST816S is a touch sensor from Hynitron with integrated gesture
* detection. It is able to measure both the position of a single finger and a
* number of basic gestures. The PineTime board has one of these for the touch
* screen.
*
* Documentation about the specifics is very limited and most of this driver is
* based on experimenting with the chip and from community effort on the
* PineTime.
*
* Two things about the driver are noteworthy:
* 1. It only responds to I2C commands after an event, such as a touch
* detection. Do not expect it to respond on init. Instead after a touch
* event, it will assert the IRQ and respond to I2C reads for a short time.
* 2. While it should be able to detect multiple finger events, this version of
* the chip always returns only a single finger event and a gesture.
*
* Reading the display data multiple times during a single event will return the
* last sampled finger position.
*
* @{
* @file
* @brief Device driver interface for the CST816S touch screen
*
* @author Koen Zandberg <koen@bergzand.net>
*/
#ifndef CST816S_H
#define CST816S_H
#include <stdint.h>
#include "periph/i2c.h"
#include "periph/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief callback definition
*/
typedef void (*cst816s_irq_cb_t)(void *arg);
/**
* @brief cst816s touch event touch state
*/
typedef enum {
CST816S_TOUCH_DOWN = 0, /**< Touch press */
CST816S_TOUCH_UP = 1, /**< Touch release */
CST816S_TOUCH_CONTACT = 2, /**< Touch contact */
} cst816s_touch_t;
/**
* @brief CST816S Gesture types
*/
typedef enum {
CST816S_GESTURE_NONE = 0x00, /**< no gesture detected */
CST816S_GESTURE_SLIDE_DOWN = 0x01, /**< downward slide detected */
CST816S_GESTURE_SLIDE_UP = 0x02, /**< upward slide detected */
CST816S_GESTURE_SLIDE_LEFT = 0x03, /**< left slide detected */
CST816S_GESTURE_SLIDE_RIGHT = 0x04, /**< right slide detected */
CST816S_GESTURE_SINGLE_CLICK = 0x05, /**< single click detected */
CST816S_GESTURE_DOUBLE_CLICK = 0x0b, /**< double click detected */
CST816S_GESTURE_LONG_PRESS = 0x0c, /**< long press detected */
} cst816s_gesture_t;
/**
* @brief string versions of the cst816 gestures
*/
extern const char *cst816s_gesture_str[];
/**
* @brief cst816s touch event data
*/
typedef struct {
cst816s_gesture_t gesture; /**< Detected gesture */
cst816s_touch_t action; /**< Press or release event */
uint16_t x; /**< X coordinate */
uint16_t y; /**< Y coordinate */
} cst816s_touch_data_t;
/**
* @brief cst816s driver struct
*/
typedef struct {
i2c_t i2c_dev; /**< I2C device which is used */
uint8_t i2c_addr; /**< I2C address */
gpio_t irq; /**< IRQ pin */
gpio_flank_t irq_flank; /**< IRQ flank */
gpio_t reset; /**< Device reset GPIO */
} cst816s_params_t;
/**
* @brief cst816s device descriptor
*/
typedef struct {
const cst816s_params_t *params; /**< Device parameters */
cst816s_irq_cb_t cb; /**< Configured IRQ event callback */
void *cb_arg; /**< Extra argument for the callback */
} cst816s_t;
/**
* @brief Status and error return codes
*/
enum {
CST816S_OK = 0, /**< everything was fine */
CST816S_ERR_IRQ = -1, /**< IRQ initialization error */
};
/**
* @brief Initialize the given cst816s device
*
* @param[out] dev device descriptor of the given cst816s device
* @param[in] params static configuration parameters
* @param[in] cb callback for the cst816s event interrupt, may be NULL
* @param[in] arg extra argument passed to the event interrupt.
*
* @returns CST816S_OK on success
* @returns CST816S_ERR_IRQ on IRQ initialization error
*/
int cst816s_init(cst816s_t *dev, const cst816s_params_t *params,
cst816s_irq_cb_t cb, void *arg);
/**
* @brief Read touch data from the cst816s device
*
* @param[in] dev device descriptor
* @param[out] data Touch data
*
* @returns 0 on success
* @returns negative on I2C access error
*/
int cst816s_read(const cst816s_t *dev, cst816s_touch_data_t *data);
#ifdef __cplusplus
}
#endif
#endif /* CST816S_H */
/** @} */

View File

@ -0,0 +1,6 @@
include ../Makefile.tests_common
USEMODULE += cst816s
USEMODULE += core_thread_flags
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2020 Koen Zandberg
*
* 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 tests
* @{
*
* @file
* @brief Test application for the CST816S touch screen driver
*
* @author Koen Zandberg <koen@bergzand.net>
*
* @}
*/
#include <stdlib.h>
#include <stdio.h>
#include "cst816s_params.h"
#include "cst816s.h"
#include "thread.h"
#include "thread_flags.h"
#define CST816S_THREAD_FLAG (1 << 8)
#define CST816S_NUM_TOUCHES 5
static void _cb(void *arg)
{
kernel_pid_t *pid = arg;
thread_flags_set((thread_t *)sched_threads[*pid], CST816S_THREAD_FLAG);
}
static void _dump_cst816s(cst816s_t *dev)
{
puts("Reading data:");
cst816s_touch_data_t touches;
if (cst816s_read(dev, &touches) == 0) {
printf("Touch at %03u, %03u with gesture type \"%s\"\n", touches.x,
touches.y, cst816s_gesture_str[touches.gesture]);
}
else {
puts("Device not responding");
}
}
int main(void)
{
cst816s_t dev;
kernel_pid_t pid = thread_getpid();
puts("CST816S test application\n");
cst816s_init(&dev, &cst816s_params[0], _cb, &pid);
while (1) {
thread_flags_t flags = thread_flags_wait_any(CST816S_THREAD_FLAG);
if (flags & CST816S_THREAD_FLAG) {
_dump_cst816s(&dev);
}
}
return 0;
}