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:
commit
6e21c72382
@ -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
1
drivers/cst816s/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
3
drivers/cst816s/Makefile.dep
Normal file
3
drivers/cst816s/Makefile.dep
Normal file
@ -0,0 +1,3 @@
|
||||
FEATURES_REQUIRED += periph_gpio_irq
|
||||
FEATURES_REQUIRED += periph_i2c
|
||||
USEMODULE += xtimer
|
2
drivers/cst816s/Makefile.include
Normal file
2
drivers/cst816s/Makefile.include
Normal file
@ -0,0 +1,2 @@
|
||||
USEMODULE_INCLUDES_cst816s := $(LAST_MAKEFILEDIR)/include
|
||||
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_cst816s)
|
106
drivers/cst816s/cst816s.c
Normal file
106
drivers/cst816s/cst816s.c
Normal 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 */
|
||||
}
|
37
drivers/cst816s/include/cst816s_internal.h
Normal file
37
drivers/cst816s/include/cst816s_internal.h
Normal 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 */
|
||||
/** @} */
|
83
drivers/cst816s/include/cst816s_params.h
Normal file
83
drivers/cst816s/include/cst816s_params.h
Normal 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
154
drivers/include/cst816s.h
Normal 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 */
|
||||
/** @} */
|
6
tests/driver_cst816s/Makefile
Normal file
6
tests/driver_cst816s/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += cst816s
|
||||
USEMODULE += core_thread_flags
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
67
tests/driver_cst816s/main.c
Normal file
67
tests/driver_cst816s/main.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user