More logic added to the TSC2007 touchscreen driver

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3829 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2011-07-29 23:37:33 +00:00
parent ab1634636e
commit 607e574101
3 changed files with 250 additions and 17 deletions

View File

@ -48,6 +48,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <poll.h>
@ -61,6 +62,8 @@
#include <nuttx/i2c.h>
#include <nuttx/input/tsc2007.h>
#include "tsc2007.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -78,9 +81,11 @@
struct tsc2007_dev_s
{
uint8_t crefs; /* Number of times the device has been opened */
sem_t devsem; /* Manages exclusive access to this structure */
FAR struct i2c_dev_s *i2c; /* Saved I2C driver instance */
uint8_t crefs; /* Number of times the device has been opened */
sem_t devsem; /* Manages exclusive access to this structure */
FAR struct tsc2007_config_s *config; /* Board configuration data */
FAR struct i2c_dev_s *i2c; /* Saved I2C driver instance */
/* The following is a list if poll structures of threads waiting for
* driver events. The 'struct pollfd' reference for each open is also
@ -95,6 +100,16 @@ struct tsc2007_dev_s
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
#ifndef CONFIG_DISABLE_POLL
static void tsc2007_pollnotify(FAR struct tsc2007_dev_s *priv,
pollevent_t eventset);
#endif
static int tsc2007_transfer(FAR struct tsc2007_dev_s *priv, uint8_t cmd);
static void tsc2007_sample(FAR struct tsc2007_dev_s *tsc,
FAR struct tsc2007_sample_s *sample);
static int tsc2007_interrupt(int irq, FAR void *context);
/* Character driver methods */
static int tsc2007_open(FAR struct file *filep);
static int tsc2007_close(FAR struct file *filep);
@ -131,7 +146,8 @@ static const struct file_operations tsc2007_fops =
****************************************************************************/
#ifndef CONFIG_DISABLE_POLL
static void tsc2007_pollnotify(FAR struct tsc2007_dev_s *priv, pollevent_t eventset)
static void tsc2007_pollnotify(FAR struct tsc2007_dev_s *priv,
pollevent_t eventset)
{
int i;
@ -153,6 +169,121 @@ static void tsc2007_pollnotify(FAR struct tsc2007_dev_s *priv, pollevent_t event
# define tsc2007_pollnotify(priv,event)
#endif
/****************************************************************************
* Name: tsc2007_transfer
****************************************************************************/
static int tsc2007_transfer(FAR struct tsc2007_dev_s *priv, uint8_t cmd)
{
struct i2c_msg_s msg;
uint8_t data12[2];
int ret;
/* "A conversion/write cycle begins when the master issues the address
* byte containing the slave address of the TSC2007, with the eighth bit
* equal to a 0 (R/W = 0)... Once the eighth bit has been received...
* the TSC2007 issues an acknowledge.
*
* "When the master receives the acknowledge bit from the TSC2007, the
* master writes the command byte to the slave... After the command byte
* is received by the slave, the slave issues another acknowledge bit.
* The master then ends the write cycle by issuing a repeated START or a
* STOP condition...
*/
msg.addr = priv->config->address; /* 7-bit address */
msg.flags = 0; /* Write transaction, beginning with START */
msg.buffer = &cmd; /* Transfer from this address */
msg.length = 1; /* Send one byte following the address */
ret = I2C_TRANSFER(priv->i2c, &msg, 1);
if (ret < 0)
{
idbg("I2C_TRANSFER failed: %d\n", ret);
return ret;
}
/* "The input multiplexer channel for the A/D converter is selected when
* bits C3 through C0 are clocked in. If the selected channel is an X-,Y-,
* or Z-position measurement, the appropriate drivers turn on once the
* acquisition period begins.
*
* "... the input sample acquisition period starts on the falling edge of
* SCL when the C0 bit of the command byte has been latched, and ends
* when a STOP or repeated START condition has been issued. A/D conversion
* starts immediately after the acquisition period...
*
* "For best performance, the I2C bus should remain in an idle state while
* an A/D conversion is taking place. ... The master should wait for at
* least 10ms before attempting to read data from the TSC2007...
*/
usleep(10*1000);
/* "Data access begins with the master issuing a START condition followed
* by the address byte ... with R/W = 1.
*
* "When the eighth bit has been received and the address matches, the
* slave issues an acknowledge. The first byte of serial data then follows
* (D11-D4, MSB first).
*
* "After the first byte has been sent by the slave, it releases the SDA line
* for the master to issue an acknowledge. The slave responds with the
* second byte of serial data upon receiving the acknowledge from the master
* (D3-D0, followed by four 0 bits). The second byte is followed by a NOT
* acknowledge bit (ACK = 1) from the master to indicate that the last
* data byte has been received...
*/
msg.addr = priv->config->address; /* 7-bit address */
msg.flags = I2C_M_READ; /* Read transaction, beginning with START */
msg.buffer = data12; /* Transfer two this address */
msg.length = 2; /* Read two bytes following the address */
ret = I2C_TRANSFER(priv->i2c, &msg, 1);
if (ret < 0)
{
idbg("I2C_TRANSFER failed: %d\n", ret);
return ret;
}
ret = (unsigned int)data12[0] << 4 | (unsigned int)data12[1];
ivdbg(&tsc->client->dev, "data: 0x%03x\n", ret);
return ret;
}
/****************************************************************************
* Name: tsc2007_sample
****************************************************************************/
static void tsc2007_sample(FAR struct tsc2007_dev_s *tsc,
FAR struct tsc2007_sample_s *sample)
{
/* ADC is on... Disable interrupts and read Y and X positions */
sample->y = tsc2007_transfer(tsc, (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YPOS));
sample->x = tsc2007_transfer(tsc, (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XPOS));
/* Read Z1 and Z2 positions */
sample->z1 = tsc2007_transfer(tsc, (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z1POS));
sample->z2 = tsc2007_transfer(tsc, (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z2POS));
/* Power down ADC and enable PENIRQ */
(void)tsc2007_transfer(tsc, (TSC2007_CMD_12BIT | TSC2007_CMD_PWRDN_IRQEN));
}
/****************************************************************************
* Name: tsc2007_interrupt
****************************************************************************/
static int tsc2007_interrupt(int irq, FAR void *context)
{
# warning "Missing logic"
return -ENOSYS;
}
/****************************************************************************
* Name: tsc2007_open
****************************************************************************/
@ -475,8 +606,9 @@ errout:
* number
*
* Input Parameters:
* dev - An I2C driver instance
* minor - The input device minor number
* dev - An I2C driver instance
* config - Persistant board configuration data
* minor - The input device minor number
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
@ -484,14 +616,16 @@ errout:
*
****************************************************************************/
int tsc2007_register(FAR struct i2c_dev_s *dev, int minor)
int tsc2007_register(FAR struct i2c_dev_s *dev,
FAR struct tsc2007_config_s *config, int minor)
{
FAR struct tsc2007_dev_s *priv;
char devname[DEV_NAMELEN];
int ret;
ivdbg("dev: %p minor: %d\n", dev, minor);
DEBUGASSERT(dev != NULL && minor > 0 && minor < 100);
DEBUGASSERT(dev != NULL && config != NULL && minor > 0 && minor < 100);
DEBUGASSERT((config->address & 0xfc) == 0x48);
/* Create and initialize a TSC2007 device driver instance */
@ -502,12 +636,34 @@ int tsc2007_register(FAR struct i2c_dev_s *dev, int minor)
return -ENOMEM;
}
/* Initialize a TSC2007 device driver instance */
/* Initialize the TSC2007 device driver instance */
priv->i2c = dev;
sem_init(&priv->devsem, 0, 1);
memset(priv, 0, sizeof(struct tsc2007_dev_s));
priv->i2c = dev; /* Save the I2C device handle */
priv->config = config; /* Save the board configuration */
sem_init(&priv->devsem, 0, 1); /* Initialize device structure semaphore */
/* Register the input device */
/* Attach the interrupt handler */
ret = config->attach(config, tsc2007_interrupt);
if (ret < 0)
{
idbg("Failed to attach interrupt\n");
goto errout_with_priv;
}
/* Power down the ADC and enable PENIRQ. This is the normal state while
* waiting for a touch event.
*/
ret = tsc2007_transfer(priv, (TSC2007_CMD_12BIT | TSC2007_CMD_PWRDN_IRQEN));
if (ret < 0)
{
idbg("tsc2007_transfer failed: %d\n", ret);
goto errout_with_priv;
}
/* Register the device as an input device */
(void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor);
ivdbg("Registering %s\n", devname);
@ -515,6 +671,21 @@ int tsc2007_register(FAR struct i2c_dev_s *dev, int minor)
if (ret < 0)
{
idbg("register_driver() failed: %d\n", ret);
goto errout_with_priv;
}
/* Enable the interrupt */
ret = config->enable(config, true);
if (ret < 0)
{
idbg("Failed enable interrupt\n");
goto errout_with_priv;
}
return ret;
errout_with_priv:
sem_destroy(&priv->devsem);
kfree(priv);
return ret;
}

View File

@ -51,6 +51,7 @@
/* TSC2007 Address */
#define TSC2007_ADDRESS_MASK (0xf8) /* Bits 3-7: Invariant part of TSC2007 address */
#define TSC2007_ADDRESS (0x90) /* Bits 3-7: Always set at '10010' */
#define TSC2007_A1 (1 << 2) /* Bit 2: A1 */
#define TSC2007_A0 (1 << 1) /* Bit 1: A1 */
@ -71,7 +72,7 @@
# define TSC2007_CMD_FUNC_XPOS (12 << TSC2007_CMD_FUNC_SHIFT) /* Measure X position */
# define TSC2007_CMD_FUNC_YPOS (13 << TSC2007_CMD_FUNC_SHIFT) /* Measure Y position */
# define TSC2007_CMD_FUNC_Z1POS (14 << TSC2007_CMD_FUNC_SHIFT) /* Measure Z1 position */
# define TSC2007_CMD_FUNC_Z2POS (15 << TSC2007_CMD_FUNC_SHIFT) /*Measure Z2 positionn */
# define TSC2007_CMD_FUNC_Z2POS (15 << TSC2007_CMD_FUNC_SHIFT) /* Measure Z2 positionn */
#define TSC2007_CMD_PWRDN_SHIFT (2) /* Bits 2-3: Power-down bits */
#define TSC2007_CMD_PWRDN_MASK (3 << TSC2007_CMD_PWRDN_SHIFT)
# define TSC2007_CMD_PWRDN_IRQEN (0 << TSC2007_CMD_PWRDN_SHIFT) /* 00: Power down between cycles; PENIRQ enabled */
@ -91,6 +92,20 @@
#define TSC2007_CMD_PU_50KOHM (0) /* Bit 0: 0: RIRQ = 50kOhm (default). */
#define TSC2007_CMD_PU_90KOHM (1 << 1) /* Bit 0: 1: 1: RIRQ = 90kOhm */
/********************************************************************************************
* Public Types
********************************************************************************************/
/* This structure describes the sampled TSC2007 data */
struct tsc2007_sample_s
{
uint16_t x; /* X position */
uint16_t y; /* Y position */
uint16_t z1; /* Z1 position */
uint16_t z2; /* Z2 position */
};
/********************************************************************************************
* Public Function Prototypes
********************************************************************************************/

View File

@ -60,6 +60,50 @@
# define CONFIG_TSC2007_NPOLLWAITERS 2
#endif
/* Check for some required settings. This can save the user a lot of time
* in getting the right configuration.
*/
#ifndef CONFIG_I2C_TRANSFER
# error "CONFIG_I2C_TRANSFER is required in the I2C configuration"
#endif
#ifdef CONFIG_DISABLE_SIGNALS
# error "Signals are required. CONFIG_DISABLE_SIGNALS must not be selected."
#endif
#ifndef CONFIG_SCHED_WORKQUEUE
# error "Work queue support required. CONFIG_SCHED_WORKQUEUE must be selected."
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/* A reference to a structure of this type must be passed to the TSC2007
* driver. This structure provides information about the configuration
* of the TSB2007 and provides some board-specific hooks.
*
* Memory for this structure is provided by the caller. It is not copied
* by the driver and is presumed to persist while the driver is active.
*/
struct tsc2007_config_s
{
/* Device characterization */
uint8_t address; /* 7-bit I2C address (only bits 0-6 used) */
uint16_t caldata; /* Calibrated X plate resistance data */
uint32_t frequency; /* I2C frequency */
/* IRQ/GPIO access callbacks */
int (*attach)(FAR struct tsc2007_config_s *state, xcpt_t isr);
int (*enable)(FAR struct tsc2007_config_s *state, bool enable);
int (*clear)(FAR struct tsc2007_config_s *state);
int (*pendown)(FAR struct tsc2007_config_s *state);
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
@ -80,8 +124,9 @@ extern "C" {
* number
*
* Input Parameters:
* dev - An I2C driver instance
* minor - The input device minor number
* dev - An I2C driver instance
* config - Persistant board configuration data
* minor - The input device minor number
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
@ -89,12 +134,14 @@ extern "C" {
*
****************************************************************************/
EXTERN int tsc2007_register(FAR struct i2c_dev_s *dev, int minor);
EXTERN int tsc2007_register(FAR struct i2c_dev_s *dev,
FAR struct tsc2007_config_s *config,
int minor);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endief /* CONFIG_INPUT && CONFIG_INPUT_TSC2007 */
#endif /* CONFIG_INPUT && CONFIG_INPUT_TSC2007 */
#endif /* __INCLUDE_NUTTX_INPUT_TSC2007_H */