From 04c0868c718d4c98d6af747cf08f613bc45d1c2c Mon Sep 17 00:00:00 2001 From: patacongo Date: Fri, 29 Jul 2011 23:37:33 +0000 Subject: 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 --- nuttx/drivers/input/tsc2007.c | 195 +++++++++++++++++++++++++++++++++++++++--- nuttx/drivers/input/tsc2007.h | 17 +++- 2 files changed, 199 insertions(+), 13 deletions(-) (limited to 'nuttx/drivers') diff --git a/nuttx/drivers/input/tsc2007.c b/nuttx/drivers/input/tsc2007.c index 7708253ab..919952285 100644 --- a/nuttx/drivers/input/tsc2007.c +++ b/nuttx/drivers/input/tsc2007.c @@ -48,6 +48,7 @@ #include #include +#include #include #include #include @@ -61,6 +62,8 @@ #include #include +#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 */ + + 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 */ + + /* 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. + */ - priv->i2c = dev; - sem_init(&priv->devsem, 0, 1); + 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 input device */ + /* 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; } diff --git a/nuttx/drivers/input/tsc2007.h b/nuttx/drivers/input/tsc2007.h index 27f9386a2..0ece1627d 100644 --- a/nuttx/drivers/input/tsc2007.h +++ b/nuttx/drivers/input/tsc2007.h @@ -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 ********************************************************************************************/ -- cgit v1.2.3