summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-07-30 15:31:23 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-07-30 15:31:23 +0000
commit291ccd2db69524176b349100a5710e451039a8ec (patch)
tree84b3fb4f6f18ac36555df5677a8e0dfcde91af16 /nuttx
parent04c0868c718d4c98d6af747cf08f613bc45d1c2c (diff)
downloadnuttx-291ccd2db69524176b349100a5710e451039a8ec.tar.gz
nuttx-291ccd2db69524176b349100a5710e451039a8ec.tar.bz2
nuttx-291ccd2db69524176b349100a5710e451039a8ec.zip
More TSC2007 driver updates
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3830 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_i2c.c37
-rw-r--r--nuttx/configs/vsn/src/sif.c2
-rw-r--r--nuttx/drivers/input/tsc2007.c546
-rw-r--r--nuttx/drivers/input/tsc2007.h15
-rwxr-xr-xnuttx/drivers/wireless/cc1101/cc1101.c3
-rw-r--r--nuttx/include/nuttx/i2c.h29
-rw-r--r--nuttx/include/nuttx/input/tsc2007.h35
-rwxr-xr-xnuttx/include/nuttx/wqueue.h2
8 files changed, 520 insertions, 149 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_i2c.c b/nuttx/arch/arm/src/stm32/stm32_i2c.c
index 84f099ba1..91a0aca34 100644
--- a/nuttx/arch/arm/src/stm32/stm32_i2c.c
+++ b/nuttx/arch/arm/src/stm32/stm32_i2c.c
@@ -62,6 +62,10 @@
* - Be ready for IPMI
**/
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
@@ -84,7 +88,6 @@
#include "stm32_i2c.h"
#include "stm32_waste.h"
-
#if defined(CONFIG_STM32_I2C1) || defined(CONFIG_STM32_I2C2)
/************************************************************************************
@@ -108,7 +111,6 @@ struct stm32_i2c_priv_s {
uint32_t status;
};
-
/** I2C Device, Instance
*/
struct stm32_i2c_inst_s {
@@ -120,7 +122,6 @@ struct stm32_i2c_inst_s {
uint16_t flags;
};
-
/************************************************************************************
* Private Data
************************************************************************************/
@@ -139,7 +140,6 @@ struct stm32_i2c_priv_s stm32_i2c2_priv = {
};
#endif
-
/************************************************************************************
* Private Functions
************************************************************************************/
@@ -150,21 +150,18 @@ static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv, uint8
return getreg16(priv->base + offset);
}
-
/** Put register value by offset */
static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset, uint16_t value)
{
putreg16(value, priv->base + offset);
}
-
/** Modify register value by offset */
static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset, uint16_t clearbits, uint16_t setbits)
{
modifyreg16(priv->base + offset, clearbits, setbits);
}
-
void inline stm32_i2c_sem_wait(FAR struct i2c_dev_s *dev)
{
while( sem_wait( &((struct stm32_i2c_inst_s *)dev)->priv->sem_excl ) != 0 ) {
@@ -172,7 +169,6 @@ void inline stm32_i2c_sem_wait(FAR struct i2c_dev_s *dev)
}
}
-
int inline stm32_i2c_sem_waitisr(FAR struct i2c_dev_s *dev)
{
while( sem_wait( &((struct stm32_i2c_inst_s *)dev)->priv->sem_isr ) != 0 ) {
@@ -181,27 +177,23 @@ int inline stm32_i2c_sem_waitisr(FAR struct i2c_dev_s *dev)
return OK;
}
-
void inline stm32_i2c_sem_post(FAR struct i2c_dev_s *dev)
{
sem_post( &((struct stm32_i2c_inst_s *)dev)->priv->sem_excl );
}
-
void inline stm32_i2c_sem_init(FAR struct i2c_dev_s *dev)
{
sem_init( &((struct stm32_i2c_inst_s *)dev)->priv->sem_excl, 0, 1);
sem_init( &((struct stm32_i2c_inst_s *)dev)->priv->sem_isr, 0, 0);
}
-
void inline stm32_i2c_sem_destroy(FAR struct i2c_dev_s *dev)
{
sem_destroy( &((struct stm32_i2c_inst_s *)dev)->priv->sem_excl );
sem_destroy( &((struct stm32_i2c_inst_s *)dev)->priv->sem_isr );
}
-
static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequency)
{
/* Disable Peripheral if rising time is to be changed,
@@ -238,20 +230,17 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1);
}
-
static inline void stm32_i2c_sendstart(FAR struct stm32_i2c_priv_s *priv)
{
/* Disable ACK on receive by default and generate START */
stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, I2C_CR1_START);
}
-
static inline void stm32_i2c_sendstop(FAR struct stm32_i2c_priv_s *priv)
{
stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, I2C_CR1_STOP);
}
-
static inline uint32_t stm32_i2c_getstatus(FAR struct stm32_i2c_priv_s *priv)
{
uint32_t status = stm32_i2c_getreg(priv, STM32_I2C_SR1_OFFSET);
@@ -259,7 +248,6 @@ static inline uint32_t stm32_i2c_getstatus(FAR struct stm32_i2c_priv_s *priv)
return status;
}
-
/************************************************************************************
* Interrupt Service Routines
************************************************************************************/
@@ -425,8 +413,6 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv)
priv->status = status;
return OK;
}
-
-
/* Decode ***************************************************************************/
@@ -444,7 +430,6 @@ static int stm32_i2c2_isr(int irq, void *context)
}
#endif
-
/************************************************************************************
* Private Initialization and Deinitialization
************************************************************************************/
@@ -511,7 +496,6 @@ static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
return OK;
}
-
/** Shutdown the I2C hardware */
static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
{
@@ -555,7 +539,6 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
return OK;
}
-
/************************************************************************************
* Device Driver OPS - Blocking Type
************************************************************************************/
@@ -574,7 +557,6 @@ uint32_t stm32_i2c_setfrequency(FAR struct i2c_dev_s *dev, uint32_t frequency)
return ((struct stm32_i2c_inst_s *)dev)->frequency;
}
-
int stm32_i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits)
{
stm32_i2c_sem_wait(dev);
@@ -586,7 +568,6 @@ int stm32_i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits)
return OK;
}
-
int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int count)
{
struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev;
@@ -666,7 +647,6 @@ int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int
return -status_errno;
}
-
int stm32_i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen)
{
stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
@@ -681,7 +661,6 @@ int stm32_i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen
return stm32_i2c_process(dev, &msgv, 1);
}
-
int stm32_i2c_read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen)
{
stm32_i2c_sem_wait(dev); /* ensure that address or flags don't change meanwhile */
@@ -696,7 +675,6 @@ int stm32_i2c_read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen)
return stm32_i2c_process(dev, &msgv, 1);
}
-
#ifdef CONFIG_I2C_WRITEREAD
int stm32_i2c_writeread(FAR struct i2c_dev_s *dev, const uint8_t *wbuffer, int wbuflen,
uint8_t *buffer, int buflen)
@@ -722,7 +700,6 @@ int stm32_i2c_writeread(FAR struct i2c_dev_s *dev, const uint8_t *wbuffer, int w
}
#endif
-
#ifdef CONFIG_I2C_TRANSFER
int stm32_i2c_transfer(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int count)
{
@@ -731,7 +708,6 @@ int stm32_i2c_transfer(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, in
}
#endif
-
/************************************************************************************
* Device Structures, Instantiation
************************************************************************************/
@@ -740,9 +716,9 @@ struct i2c_ops_s stm32_i2c_ops = {
.setfrequency = stm32_i2c_setfrequency,
.setaddress = stm32_i2c_setaddress,
.write = stm32_i2c_write,
- .read = stm32_i2c_read,
+ .read = stm32_i2c_read
#ifdef CONFIG_I2C_WRITEREAD
- .writeread = stm32_i2c_writeread
+ , .writeread = stm32_i2c_writeread
#endif
#ifdef CONFIG_I2C_TRANSFER
, .transfer = stm32_i2c_transfer
@@ -753,7 +729,6 @@ struct i2c_ops_s stm32_i2c_ops = {
#endif
};
-
/************************************************************************************
* Public Function - Initialization
************************************************************************************/
diff --git a/nuttx/configs/vsn/src/sif.c b/nuttx/configs/vsn/src/sif.c
index 456f38a30..0e08280de 100644
--- a/nuttx/configs/vsn/src/sif.c
+++ b/nuttx/configs/vsn/src/sif.c
@@ -496,7 +496,7 @@ int sif_init(void)
* Provides direct access to the sensor connector, readings, and diagnostic.
**/
-extern int cc1101_eventcb(int irq, FAR void *context)
+extern int cc1101_eventcb(int irq, FAR void *context);
int sif_main(int argc, char *argv[])
{
diff --git a/nuttx/drivers/input/tsc2007.c b/nuttx/drivers/input/tsc2007.c
index 919952285..7af6711bc 100644
--- a/nuttx/drivers/input/tsc2007.c
+++ b/nuttx/drivers/input/tsc2007.c
@@ -38,6 +38,11 @@
*
****************************************************************************/
+/* The TSC2007 is an analog interface circuit for a human interface touch
+ * screen device. All peripheral functions are controlled through the command
+ * byte and onboard state machines.
+ */
+
/****************************************************************************
* Included Files
****************************************************************************/
@@ -50,6 +55,7 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
+#include <fcntl.h>
#include <semaphore.h>
#include <poll.h>
#include <errno.h>
@@ -60,6 +66,7 @@
#include <nuttx/arch.h>
#include <nuttx/fs.h>
#include <nuttx/i2c.h>
+#include <nuttx/wqueue.h>
#include <nuttx/input/tsc2007.h>
#include "tsc2007.h"
@@ -78,14 +85,33 @@
/****************************************************************************
* Private Types
****************************************************************************/
+/* This structure describes the results of one TSC2007 sample */
+
+struct tsc2007_sample_s
+{
+ bool pendown; /* Pen down state */
+ uint16_t x; /* Measured X position */
+ uint16_t y; /* Measured Y position */
+ uint16_t pressure; /* Calculated pressure */
+};
+
+/* This structure describes the state of one TSC2007 driver instance */
struct tsc2007_dev_s
{
- uint8_t crefs; /* Number of times the device has been opened */
- sem_t devsem; /* Manages exclusive access to this structure */
+#ifdef CONFIG_TSC2007_MULTIPLE
+ FAR struct tsc2007_dev_s *flink; /* Supports a singly linked list of drivers */
+#endif
+ uint8_t crefs; /* Number of times the device has been opened */
+ uint8_t nwaiters; /* Number of threads waiting for TSC2007 data */
+ volatile bool penchange; /* An unreported event is buffered */
+ sem_t devsem; /* Manages exclusive access to this structure */
+ sem_t waitsem; /* Used to wait for the availability of data */
FAR struct tsc2007_config_s *config; /* Board configuration data */
- FAR struct i2c_dev_s *i2c; /* Saved I2C driver instance */
+ FAR struct i2c_dev_s *i2c; /* Saved I2C driver instance */
+ struct work_s work; /* Supports the interrupt handling "bottom half" */
+ struct tsc2007_sample_s sample; /* Last sampled data */
/* The following is a list if poll structures of threads waiting for
* driver events. The 'struct pollfd' reference for each open is also
@@ -93,20 +119,21 @@ struct tsc2007_dev_s
*/
#ifndef CONFIG_DISABLE_POLL
- struct pollfd *fds[CONFIG_TSC2007_NPOLLWAITERS];
+ struct pollfd *fds[CONFIG_TSC2007_NPOLLWAITERS];
#endif
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
-#ifndef CONFIG_DISABLE_POLL
-static void tsc2007_pollnotify(FAR struct tsc2007_dev_s *priv,
- pollevent_t eventset);
-#endif
+
+static void tsc2007_notify(FAR struct tsc2007_dev_s *priv);
+static int tsc2007_sample(FAR struct tsc2007_dev_s *priv,
+ FAR struct tsc2007_sample_s *sample);
+static int tsc2007_waitsample(FAR struct tsc2007_dev_s *priv,
+ FAR struct tsc2007_sample_s *sample);
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 void tsc2007_worker(FAR void *arg);
static int tsc2007_interrupt(int irq, FAR void *context);
/* Character driver methods */
@@ -114,7 +141,6 @@ static int tsc2007_interrupt(int irq, FAR void *context);
static int tsc2007_open(FAR struct file *filep);
static int tsc2007_close(FAR struct file *filep);
static ssize_t tsc2007_read(FAR struct file *filep, FAR char *buffer, size_t len);
-static ssize_t tsc2007_write(FAR struct file *filep, FAR const char *buffer, size_t len);
static int tsc2007_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
#ifndef CONFIG_DISABLE_POLL
static int tsc2007_poll(FAR struct file *filep, struct pollfd *fds, bool setup);
@@ -124,12 +150,14 @@ static int tsc2007_poll(FAR struct file *filep, struct pollfd *fds, bool setup);
* Private Data
****************************************************************************/
+/* This the the vtable that supports the character driver interface */
+
static const struct file_operations tsc2007_fops =
{
tsc2007_open, /* open */
tsc2007_close, /* close */
tsc2007_read, /* read */
- tsc2007_write, /* write */
+ 0, /* write */
0, /* seek */
tsc2007_ioctl /* ioctl */
#ifndef CONFIG_DISABLE_POLL
@@ -137,37 +165,176 @@ static const struct file_operations tsc2007_fops =
#endif
};
+/* If only a single TSC2007 device is supported, then the driver state
+ * structure may as well be pre-allocated.
+ */
+
+#ifndef CONFIG_TSC2007_MULTIPLE
+static struct tsc2007_dev_s g_tsc2007;
+
+/* Otherwise, we will need to maintain allocated driver instances in a list */
+
+#else
+static struct tsc2007_dev_s *g_tsc2007list;
+#endif
+
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
- * Name: tsc2007_pollnotify
+ * Name: tsc2007_notify
****************************************************************************/
-#ifndef CONFIG_DISABLE_POLL
-static void tsc2007_pollnotify(FAR struct tsc2007_dev_s *priv,
- pollevent_t eventset)
+static void tsc2007_notify(FAR struct tsc2007_dev_s *priv)
{
+#ifndef CONFIG_DISABLE_POLL
int i;
+#endif
+
+ /* If there are threads waiting for read data, then signal one of them
+ * that the read data is available.
+ */
+
+ if (priv->nwaiters > 0)
+ {
+ /* After posting this semaphore, we need to exit because the TSC2007
+ * is no longer avaialable.
+ */
+
+ sem_post(&priv->waitsem);
+ }
+ /* If there are threads waiting on poll() for TSC2007 data to become availabe,
+ * then wake them up now. NOTE: we wake up all waiting threads because we
+ * do not know that they are going to do. If they all try to read the data,
+ * then some make end up blocking after all.
+ */
+
+#ifndef CONFIG_DISABLE_POLL
for (i = 0; i < CONFIG_TSC2007_NPOLLWAITERS; i++)
{
struct pollfd *fds = priv->fds[i];
if (fds)
{
- fds->revents |= (fds->events & eventset);
- if (fds->revents != 0)
- {
- ivdbg("Report events: %02x\n", fds->revents);
- sem_post(fds->sem);
- }
+ fds->revents |= POLLIN;
+ ivdbg("Report events: %02x\n", fds->revents);
+ sem_post(fds->sem);
}
}
-}
-#else
-# define tsc2007_pollnotify(priv,event)
#endif
+}
+
+/****************************************************************************
+ * Name: tsc2007_sample
+ ****************************************************************************/
+
+static int tsc2007_sample(FAR struct tsc2007_dev_s *priv,
+ FAR struct tsc2007_sample_s *sample)
+{
+ irqstate_t flags;
+ int ret = -EAGAIN;
+
+ /* Interrupts me be disabled when this is called to (1) prevent posting
+ * of semphores from interrupt handlers, and (2) to prevent sampled data
+ * from changing until it has been reported.
+ */
+
+ flags = irqsave();
+
+ /* Is there new TSC2007 sample data available? */
+
+ if (priv->penchange)
+ {
+ /* Yes.. the state has changed in some way. Return a copy of the
+ * sampled data.
+ */
+
+ memcpy(sample, &priv->sample, sizeof(struct tsc2007_sample_s ));
+ priv->penchange = false;
+ ret = OK;
+ }
+
+ irqrestore(flags);
+ return ret;
+}
+
+/****************************************************************************
+ * Name: tsc2007_waitsample
+ ****************************************************************************/
+
+static int tsc2007_waitsample(FAR struct tsc2007_dev_s *priv,
+ FAR struct tsc2007_sample_s *sample)
+{
+ irqstate_t flags;
+ int ret;
+
+ /* Interrupts me be disabled when this is called to (1) prevent posting
+ * of semphores from interrupt handlers, and (2) to prevent sampled data
+ * from changing until it has been reported.
+ *
+ * In addition, we will also disable pre-emption to prevent other threads
+ * from getting control while we muck with the semaphores.
+ */
+
+ sched_lock();
+ flags = irqsave();
+
+ /* Now release the semaphore that manages mutually exclusive access to
+ * the device structure. This may cause other tasks to become ready to
+ * run, but they cannot run yet because pre-emption is disabled.
+ */
+
+ sem_post(&priv->devsem);
+
+ /* Try to get the a sample... if we cannot, then wait on the semaphore
+ * that is posted when new sample data is availble.
+ */
+
+ while (tsc2007_sample(priv, sample) < 0)
+ {
+ /* Wait for a change in the TSC2007 state */
+
+ priv->nwaiters++;
+ ret = sem_wait(&priv->waitsem);
+ priv->nwaiters--;
+
+ if (ret < 0)
+ {
+ /* If we are awakened by a signal, then we need to return
+ * the failure now.
+ */
+
+ DEBUGASSERT(errno == EINTR);
+ ret = -EINTR;
+ goto errout;
+ }
+ }
+
+ /* Re-acquire the the semaphore that manages mutually exclusive access to
+ * the device structure. We may have to wait here. But we have our sample.
+ * Interrupts and pre-emption will be re-enabled while we wait.
+ */
+
+ ret = sem_wait(&priv->devsem);
+
+errout:
+ /* Then re-enable interrupts. We might get interrupt here and there
+ * could be a new sample. But no new threads will run because we still
+ * have pre-emption disabled.
+ */
+
+ irqrestore(flags);
+
+ /* Restore pre-emption. We might get suspended here but that is okay
+ * because we already have our sample. Note: this means that if there
+ * were two threads reading from the TSC2007 for some reason, the data
+ * might be read out of order.
+ */
+
+ sched_unlock();
+ return ret;
+}
/****************************************************************************
* Name: tsc2007_transfer
@@ -247,31 +414,159 @@ static int tsc2007_transfer(FAR struct tsc2007_dev_s *priv, uint8_t cmd)
return ret;
}
- ret = (unsigned int)data12[0] << 4 | (unsigned int)data12[1];
- ivdbg(&tsc->client->dev, "data: 0x%03x\n", ret);
+ /* Get the MS 12 bits from the first byte and the remaining LS 4 bits from
+ * the second byte.
+ */
+
+ ret = (unsigned int)data12[0] << 4 | (unsigned int)data12[1] >> 4;
+ ivdbg(&tsc->client->dev, "data: 0x%04x\n", ret);
return ret;
}
/****************************************************************************
- * Name: tsc2007_sample
+ * Name: tsc2007_worker
****************************************************************************/
-static void tsc2007_sample(FAR struct tsc2007_dev_s *tsc,
- FAR struct tsc2007_sample_s *sample)
+static void tsc2007_worker(FAR void *arg)
{
- /* ADC is on... Disable interrupts and read Y and X positions */
+ FAR struct tsc2007_dev_s *priv = (FAR struct tsc2007_dev_s *)arg;
+ FAR struct tsc2007_config_s *config; /* Convenience pointer */
+ bool pendown; /* true: pend is down */
+ uint16_t x; /* X position */
+ uint16_t y; /* Y position */
+ uint16_t z1; /* Z1 position */
+ uint16_t z2; /* Z2 position */
+ uint32_t pressure; /* Measured pressure */
+
+ ASSERT(priv != NULL);
+
+ /* Get a pointer the callbacks for convenience (and so the code is not so
+ * ugly).
+ */
+
+ config = priv->config;
+ DEBUGASSERT(config != NULL);
+
+ /* Check for pen up or down by reading the PENIRQ GPIO. */
- 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));
+ pendown = config->pendown(config);
- /* Read Z1 and Z2 positions */
+ /* Handle the change from pen down to pen up */
- 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));
+ if (!pendown)
+ {
+ /* Ignore the interrupt if the pen was already down */
+
+ if (!priv->sample.pendown)
+ {
+ goto errout;
+ }
+ }
+ else
+ {
+ /* Handle all pen down events. First, sample X, Y, Z1, and Z2 values.
+ *
+ * "A resistive touch screen operates by applying a voltage across a
+ * resistor network and measuring the change in resistance at a given
+ * point on the matrix where the screen is touched by an input (stylus,
+ * pen, or finger). The change in the resistance ratio marks the location
+ * on the touch screen.
+ *
+ * "The 4-wire touch screen panel works by applying a voltage across the
+ * vertical or horizontal resistive network. The A/D converter converts
+ * the voltage measured at the point where the panel is touched. A measurement
+ * of the Y position of the pointing device is made by connecting the X+
+ * input to a data converter chip, turning on the Y+ and Y– drivers, and
+ * digitizing the voltage seen at the X+ input ..."
+ *
+ * "... it is recommended that whenever the host writes to the TSC2007, the
+ * master processor masks the interrupt associated to PENIRQ. This masking
+ * prevents false triggering of interrupts when the PENIRQ line is disabled
+ * in the cases previously listed."
+ */
+
+ y = tsc2007_transfer(priv,
+ (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_YPOS));
+
+ /* "Voltage is then applied to the other axis, and the A/D converter
+ * converts the voltage representing the X position on the screen. This
+ * process provides the X and Y coordinates to the associated processor."
+ */
+
+ x = tsc2007_transfer(priv,
+ (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_XPOS));
+
+ /* "... To determine pen or finger touch, the pressure of the touch must be
+ * determined. ... There are several different ways of performing this
+ * measurement. The TSC2007 supports two methods. The first method requires
+ * knowing the X-plate resistance, the measurement of the X-position, and two
+ * additional cross panel measurements (Z2 and Z1) of the touch screen."
+ *
+ * Rtouch = Rxplate * (X / 4096)* (Z2/Z1 - 1)
+ *
+ * "The second method requires knowing both the X-plate and Y-plate
+ * resistance, measurement of X-position and Y-position, and Z1 ..."
+ *
+ * Rtouch = Rxplate * (X / 4096) * (4096/Z1 - 1) - Ryplate * (1 - Y/4096)
+ *
+ * Read Z1 and Z2 values.
+ */
- /* Power down ADC and enable PENIRQ */
+ z1 = tsc2007_transfer(priv,
+ (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z1POS));
+ z2 = tsc2007_transfer(priv,
+ (TSC2007_CMD_12BIT | TSC2007_CMD_ADCON_IRQDIS | TSC2007_CMD_FUNC_Z2POS));
- (void)tsc2007_transfer(tsc, (TSC2007_CMD_12BIT | TSC2007_CMD_PWRDN_IRQEN));
+ /* Power down ADC and enable PENIRQ */
+
+ (void)tsc2007_transfer(priv,
+ (TSC2007_CMD_12BIT | TSC2007_CMD_PWRDN_IRQEN));
+
+ /* Now calculate the pressure using the first method, reduced to:
+ *
+ * Rtouch = X * Rxplate *(Z2 - Z1) * / Z1 / 4096
+ */
+
+ if (z1 == 0)
+ {
+ idbg("Z1 zero\n");
+ goto errout;
+ }
+
+ pressure = (x * config->rxplate * (z2 - z1)) / z1;
+ pressure = (pressure + 2048) >> 12;
+
+ ivdbg("Position: (%d,%4d) pressure: %u z1/2: (%d,%d)\n"
+ x, y, pressure, z1, z2);
+
+ /* Ignore out of range caculcations */
+
+ if (pressure > 0x0fff)
+ {
+ idbg("Dropped out-of-range pressure: %d\n", pressure);
+ goto errout;
+ }
+
+ /* Save the measurements */
+
+ priv->sample.x = x;
+ priv->sample.y = y;
+ priv->sample.pressure = pressure;
+ }
+
+ /* Note the availability of new measurements */
+
+ priv->sample.pendown = pendown;
+ priv->penchange = true;
+
+ /* Notify any waiters that nes TSC2007 data is available */
+
+ tsc2007_notify(priv);
+
+ /* Exit, re-enabling TSC2007 interrupts */
+
+errout:
+ config->enable(config, true);
}
/****************************************************************************
@@ -280,8 +575,49 @@ static void tsc2007_sample(FAR struct tsc2007_dev_s *tsc,
static int tsc2007_interrupt(int irq, FAR void *context)
{
-# warning "Missing logic"
- return -ENOSYS;
+ FAR struct tsc2007_dev_s *priv;
+ FAR struct tsc2007_config_s *config;
+ int ret;
+
+ /* Which TSC2007 device caused the interrupt? */
+
+#ifndef CONFIG_TSC2007_MULTIPLE
+ priv = &g_tsc2007;
+#else
+ for (priv = g_tsc2007list;
+ priv && priv->configs->irq != irq;
+ priv = priv->flink);
+
+ ASSERT(priv != NULL);
+#endif
+
+ /* Get a pointer the callbacks for convenience (and so the code is not so
+ * ugly).
+ */
+
+ config = priv->config;
+ DEBUGASSERT(config != NULL);
+
+ /* Disable further interrupts */
+
+ config->enable(config, false);
+
+ /* Transfer processing to the worker thread. Since TSC2007 interrupts are
+ * disabled while the work is pending, no special action should be required
+ * to protected the work queue.
+ */
+
+ DEBUGASSERT(priv->work.worker == NULL);
+ ret = work_queue(&priv->work, tsc2007_worker, priv, 0);
+ if (ret != 0)
+ {
+ illdbg("Failed to queue work: %d\n", ret);
+ }
+
+ /* Clear any pending interrupts and return success */
+
+ config->clear(config);
+ return OK;
}
/****************************************************************************
@@ -398,6 +734,7 @@ static ssize_t tsc2007_read(FAR struct file *filep, FAR char *buffer, size_t len
{
FAR struct inode *inode;
FAR struct tsc2007_dev_s *priv;
+ struct tsc2007_sample_s sample;
int ret;
DEBUGASSERT(filep);
@@ -417,42 +754,42 @@ static ssize_t tsc2007_read(FAR struct file *filep, FAR char *buffer, size_t len
return -EINTR;
}
-#warning "Not implemented"
+ /* Try to read sample data. */
- sem_post(&priv->devsem);
- return -ENOSYS;
-}
-
-/****************************************************************************
- * Name: tsc2007_write
- ****************************************************************************/
+ ret = tsc2007_sample(priv, &sample);
+ if (ret < 0)
+ {
+ /* Sample data is not available now. We would ave to wait to get
+ * receive sample data. If the user has specified the O_NONBLOCK
+ * option, then just return an error.
+ */
-static ssize_t tsc2007_write(FAR struct file *filep, FAR const char *buffer, size_t len)
-{
- FAR struct inode *inode;
- FAR struct tsc2007_dev_s *priv;
- int ret;
+ if (filep->f_oflags & O_NONBLOCK)
+ {
+ ret = -EAGAIN;
+ goto errout;
+ }
- DEBUGASSERT(filep);
- inode = filep->f_inode;
+ /* Wait for sample data */
- DEBUGASSERT(inode && inode->i_private);
- priv = (FAR struct tsc2007_dev_s *)inode->i_private;
+ ret = tsc2007_waitsample(priv, &sample);
+ if (ret < 0)
+ {
+ /* We might have been awakened by a signal */
- /* Get exclusive access to the driver data structure */
+ goto errout;
+ }
+ }
- ret = sem_wait(&priv->devsem);
- if (ret < 0)
- {
- /* This should only happen if the wait was canceled by an signal */
+ /* In any event, we now have sampled TSC2007 data that we can report
+ * to the caller.
+ */
- DEBUGASSERT(errno == EINTR);
- return -EINTR;
- }
+#warning "Missing logic"
-#warning "Not implemented"
+errout:
sem_post(&priv->devsem);
- return -ENOSYS;
+ return ret;
}
/****************************************************************************
@@ -533,6 +870,14 @@ static int tsc2007_poll(FAR struct file *filep, FAR struct pollfd *fds,
if (setup)
{
+ /* Ignore waits that do not include POLLIN */
+
+ if ((fds->revents & POLLIN) == 0)
+ {
+ ret = -EDEADLK;
+ goto errout;
+ }
+
/* This is a request to set up the poll. Find an available
* slot for the poll structure reference
*/
@@ -545,7 +890,7 @@ static int tsc2007_poll(FAR struct file *filep, FAR struct pollfd *fds,
{
/* Bind the poll structure and this slot */
- priv->fds[i] = fds;
+ priv->fds[i] = fds;
fds->priv = &priv->fds[i];
break;
}
@@ -558,24 +903,19 @@ static int tsc2007_poll(FAR struct file *filep, FAR struct pollfd *fds,
goto errout;
}
- /* Should immediately notify on any of the requested events? */
-#warning "Missing logic"
-
+ /* Should we immediately notify on any of the requested events? */
+ if (priv->penchange)
+ {
+ tsc2007_notify(priv);
+ }
}
else if (fds->priv)
{
/* This is a request to tear down the poll. */
struct pollfd **slot = (struct pollfd **)fds->priv;
-
-#ifdef CONFIG_DEBUG
- if (!slot)
- {
- ret = -EIO;
- goto errout;
- }
-#endif
+ DEBUGASSERT(slot != NULL);
/* Remove all memory of the poll setup */
@@ -621,20 +961,32 @@ int tsc2007_register(FAR struct i2c_dev_s *dev,
{
FAR struct tsc2007_dev_s *priv;
char devname[DEV_NAMELEN];
+#ifdef CONFIG_TSC2007_MULTIPLE
+ irqstate_t flags;
+#endif
int ret;
ivdbg("dev: %p minor: %d\n", dev, minor);
+
+ /* Debug-only sanity checks */
+
DEBUGASSERT(dev != NULL && config != NULL && minor > 0 && minor < 100);
DEBUGASSERT((config->address & 0xfc) == 0x48);
+ DEBUGASSERT(config->attach != NULL && config->enable != NULL
+ config->clear != NULL && config->pendown != NULL);
/* Create and initialize a TSC2007 device driver instance */
+#ifndef CONFIG_TSC2007_MULTIPLE
+ priv = &g_tsc2007;
+#else
priv = (FAR struct tsc2007_dev_s *)kmalloc(sizeof(struct tsc2007_dev_s));
if (!priv)
{
idbg("kmalloc(%d) failed\n", sizeof(struct tsc2007_dev_s));
return -ENOMEM;
}
+#endif
/* Initialize the TSC2007 device driver instance */
@@ -642,6 +994,12 @@ int tsc2007_register(FAR struct i2c_dev_s *dev,
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 */
+ sem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */
+
+ /* Make sure that interrupts are disabled */
+
+ config->clear(config);
+ config->enable(config, false);
/* Attach the interrupt handler */
@@ -667,6 +1025,7 @@ int tsc2007_register(FAR struct i2c_dev_s *dev,
(void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor);
ivdbg("Registering %s\n", devname);
+
ret = register_driver(devname, &tsc2007_fops, 0666, priv);
if (ret < 0)
{
@@ -674,18 +1033,37 @@ int tsc2007_register(FAR struct i2c_dev_s *dev,
goto errout_with_priv;
}
- /* Enable the interrupt */
+ /* If multiple TSC2007 devices are supported, then we will need to add
+ * this new instance to a list of device instances so that it can be
+ * found by the interrupt handler based on the recieved IRQ number.
+ */
- ret = config->enable(config, true);
- if (ret < 0)
+#ifdef CONFIG_TSC2007_MULTIPLE
+ priv = irqsave;
+ priv->flink = g_tsc2007list;
+ g_tsc2007list = priv;
+ irqrestore(flags);
+#endif
+
+ /* Schedule work to perform the initial sampling and to set the data
+ * availability conditions.
+ */
+
+ ret = work_queue(&priv->work, tsc2007_worker, priv, 0);
+ if (ret != 0)
{
- idbg("Failed enable interrupt\n");
+ idbg("Failed to queue work: %d\n", ret);
goto errout_with_priv;
}
- return ret;
+
+ /* And return success (?) */
+
+ return OK;
errout_with_priv:
sem_destroy(&priv->devsem);
+#ifdef CONFIG_TSC2007_MULTIPLE
kfree(priv);
+#endif
return ret;
}
diff --git a/nuttx/drivers/input/tsc2007.h b/nuttx/drivers/input/tsc2007.h
index 0ece1627d..067d6ba3b 100644
--- a/nuttx/drivers/input/tsc2007.h
+++ b/nuttx/drivers/input/tsc2007.h
@@ -38,6 +38,11 @@
*
********************************************************************************************/
+/* The TSC2007 is an analog interface circuit for a human interface touch screen device.
+ * All peripheral functions are controlled through the command byte and onboard state
+ * machines.
+ */
+
#ifndef __DRIVERS_INPUT_TSC2007_H
#define __DRIVERS_INPUT_TSC2007_H
@@ -96,16 +101,6 @@
* 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
********************************************************************************************/
diff --git a/nuttx/drivers/wireless/cc1101/cc1101.c b/nuttx/drivers/wireless/cc1101/cc1101.c
index b13a8bc6d..e2fae9620 100755
--- a/nuttx/drivers/wireless/cc1101/cc1101.c
+++ b/nuttx/drivers/wireless/cc1101/cc1101.c
@@ -452,7 +452,8 @@ volatile int cc1101_interrupt = 0;
int cc1101_eventcb(int irq, FAR void *context)
{
- cc1101_interrupt++;
+ cc1101_interrupt++;
+ return OK;
}
/****************************************************************************
diff --git a/nuttx/include/nuttx/i2c.h b/nuttx/include/nuttx/i2c.h
index 748b7cc60..56c1d8101 100644
--- a/nuttx/include/nuttx/i2c.h
+++ b/nuttx/include/nuttx/i2c.h
@@ -87,7 +87,7 @@
* i2c_dev_s instance and will be used with all transfers. Required.
*
* Input Parameters:
- * dev - Device-specific state data
+ * dev - Device-specific state data
* frequency - The I2C frequency requested
*
* Returned Value:
@@ -105,9 +105,9 @@
* i2c_dev_s instance and will be used with all transfers. Required.
*
* Input Parameters:
- * dev - Device-specific state data
+ * dev - Device-specific state data
* address - The I2C slave address
- * nbits - The number of address bits provided (7 or 10)
+ * nbits - The number of address bits provided (7 or 10)
*
* Returned Value:
* Returns OK on success; a negated errno on failure.
@@ -129,10 +129,10 @@
* to handle reads and writes from a master.
*
* Input Parameters:
- * dev - Device-specific state data
+ * dev - Device-specific state data
* address - Our own slave address; If it is 0x00, then the device driver
* listens to general call
- * nbits - The number of address bits provided (7 or 10)
+ * nbits - The number of address bits provided (7 or 10)
*
* Returned Value:
* OK on valid address and if the same address has not been assigned
@@ -152,7 +152,7 @@
* and pend until this write completes. Required.
*
* Input Parameters:
- * dev - Device-specific state data
+ * dev - Device-specific state data
* buffer - A pointer to the read-only buffer of data to be written to device
* buflen - The number of bytes to send from the buffer
*
@@ -173,7 +173,7 @@
* and pend until this read completes. Required.
*
* Input Parameters:
- * dev - Device-specific state data
+ * dev - Device-specific state data
* buffer - A pointer to a buffer of data to receive the data from the device
* buflen - The requested number of bytes to be read
*
@@ -193,7 +193,7 @@
* It provides a convenient wrapper to the transfer function.
*
* Input Parameters:
- * dev - Device-specific state data
+ * dev - Device-specific state data
* wbuffer - A pointer to the read-only buffer of data to be written to device
* wbuflen - The number of bytes to send from the buffer
* rbuffer - A pointer to a buffer of data to receive the data from the device
@@ -216,8 +216,8 @@
* will be serialized and pend until this read completes. Optional.
*
* Input Parameters:
- * dev - Device-specific state data
- * msgs - A pointer to a set of message descriptors
+ * dev - Device-specific state data
+ * msgs - A pointer to a set of message descriptors
* msgcount - The number of transfers to perform
*
* Returned Value:
@@ -261,10 +261,10 @@ struct i2c_ops_s
struct i2c_msg_s
{
- uint16_t addr; /* Slave address */
- uint16_t flags; /* See I2C_M_* definitions */
- uint8_t *buffer;
- int length;
+ uint16_t addr; /* Slave address */
+ uint16_t flags; /* See I2C_M_* definitions */
+ uint8_t *buffer;
+ int length;
};
/* I2C private data. This structure only defines the initial fields of the
@@ -308,7 +308,6 @@ extern "C" {
EXTERN FAR struct i2c_dev_s *up_i2cinitialize(int port);
-
/****************************************************************************
* Name: up_i2cuninitialize
*
diff --git a/nuttx/include/nuttx/input/tsc2007.h b/nuttx/include/nuttx/input/tsc2007.h
index 10e5d778d..8956c61b9 100644
--- a/nuttx/include/nuttx/input/tsc2007.h
+++ b/nuttx/include/nuttx/input/tsc2007.h
@@ -38,6 +38,11 @@
*
****************************************************************************/
+/* The TSC2007 is an analog interface circuit for a human interface touch
+ * screen device. All peripheral functions are controlled through the command
+ * byte and onboard state machines.
+ */
+
#ifndef __INCLUDE_NUTTX_INPUT_TSC2007_H
#define __INCLUDE_NUTTX_INPUT_TSC2007_H
@@ -85,7 +90,9 @@
* 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.
+ * by the driver and is presumed to persist while the driver is active. The
+ * memory must be writable because, under certain circumstances, the driver
+ * may modify frequency or X plate resistance values.
*/
struct tsc2007_config_s
@@ -93,15 +100,31 @@ 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 */
+ uint16_t rxplate; /* Calibrated X plate resistance */
uint32_t frequency; /* I2C frequency */
- /* IRQ/GPIO access callbacks */
+ /* If multiple TSC2007 devices are supported, then an IRQ number must
+ * be provided for each so that their interrupts can be distinguished.
+ */
+
+#ifndef CONFIG_TSC2007_MULTIPLE
+ int irq; /* IRQ number received by interrupt handler. */
+#endif
+
+ /* IRQ/GPIO access callbacks. These operations all hidden behind
+ * callbacks to isolate the TSC2007 driver from differences in GPIO
+ * interrupt handling by varying boards and MCUs.
+ *
+ * attach - Attach the TSC2007 interrupt handler to the GPIO interrupt
+ * enable - Enable or disable the GPIO interrupt
+ * clear - Acknowledge/clear any pending GPIO interrupt
+ * pendown - Return the state of the pen down GPIO input
+ */
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);
+ void (*enable)(FAR struct tsc2007_config_s *state, bool enable);
+ void (*clear)(FAR struct tsc2007_config_s *state);
+ bool (*pendown)(FAR struct tsc2007_config_s *state);
};
/****************************************************************************
diff --git a/nuttx/include/nuttx/wqueue.h b/nuttx/include/nuttx/wqueue.h
index 2e4cd3e4e..5f5fecef8 100755
--- a/nuttx/include/nuttx/wqueue.h
+++ b/nuttx/include/nuttx/wqueue.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/wqueue.h
*
- * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without