summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-10-01 11:23:24 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-10-01 11:23:24 -0600
commit9eac480667c5fb681b9f3a80798236461071ce64 (patch)
tree3ee0a0de0f9f2bf9af83b2ad8074105752fb44c5
parent34b4c34a810f90949a3eed7854879071eb7a5d3e (diff)
downloadnuttx-9eac480667c5fb681b9f3a80798236461071ce64.tar.gz
nuttx-9eac480667c5fb681b9f3a80798236461071ce64.tar.bz2
nuttx-9eac480667c5fb681b9f3a80798236461071ce64.zip
SAMA5 touchscreen and ADC: A little more progress
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/arch/arm/src/sama5/sam_adc.c289
-rw-r--r--nuttx/arch/arm/src/sama5/sam_touchscreen.c288
3 files changed, 387 insertions, 192 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 46b235351..ca448cd4a 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -5683,7 +5683,7 @@
no serial driver) (from Alan Carvalho de Assis, 2013-9-30).
* configs/freedom-kl25z/minnsh: A new configuration that is
an experiement to see how small we can get the NuttX footprint.
- From Carvalho de Assis. (2013-9-30).
+ From Alan Carvalho de Assis. (2013-9-30).
* net/net_sendfile: The high performance sendfile logic is
now functional. From Max Holtzberg (2013-9-30).
* tools/define.sh: 'cut' long because as it once did. Script
diff --git a/nuttx/arch/arm/src/sama5/sam_adc.c b/nuttx/arch/arm/src/sama5/sam_adc.c
index d8b58010d..cc6e94561 100644
--- a/nuttx/arch/arm/src/sama5/sam_adc.c
+++ b/nuttx/arch/arm/src/sama5/sam_adc.c
@@ -57,6 +57,7 @@
#include "chip.h"
#include "chip/sam_adc.h"
+#include "sam_dmac.h"
#include "sam_adc.h"
#if defined(CONFIG_SAMA5_ADC)
@@ -123,6 +124,19 @@
SAMA5_CHAN6_ENABLE || SAMA5_CHAN7_ENABLE || SAMA5_CHAN8_ENABLE || \
SAMA5_CHAN9_ENABLE || SAMA5_CHAN10_ENABLE || SAMA5_CHAN11_ENABLE)
+/* DMA configuration flags */
+
+#ifdef CONFIG_SAMA5_ADC_DMA
+# define DMA_FLAGS \
+ DMACH_FLAG_FIFOCFG_LARGEST | \
+ ((SAM_IRQ_ADC << DMACH_FLAG_PERIPHPID_SHIFT) | DMACH_FLAG_PERIPHAHB_AHB_IF2 | \
+ DMACH_FLAG_PERIPHH2SEL | DMACH_FLAG_PERIPHISPERIPH | \
+ DMACH_FLAG_PERIPHWIDTH_16BITS | DMACH_FLAG_PERIPHCHUNKSIZE_1 | \
+ ((0x3f) << DMACH_FLAG_MEMPID_SHIFT) | DMACH_FLAG_MEMAHB_AHB_IF0 | \
+ DMACH_FLAG_MEMWIDTH_16BITS | DMACH_FLAG_MEMINCREMENT | \
+ DMACH_FLAG_MEMCHUNKSIZE_1)
+#endif
+
/****************************************************************************
* Private Types
****************************************************************************/
@@ -133,6 +147,10 @@ struct sam_adc_s
{
#ifdef SAMA5_ADC_HAVE_CHANNELS
struct adc_dev_s dev; /* The external via of the ADC device */
+
+#ifdef CONFIG_SAMA5_ADC_DMA
+ DMA_HANDLE dma; /* Handle for DMA channel */
+#endif
#endif
/* Debug stuff */
@@ -155,6 +173,14 @@ static bool sam_adc_checkreg(struct sam_adc_s *priv, bool wr,
uint32_t regval, uintptr_t address);
#endif
+/* DMA helper functions */
+
+#ifdef CONFIG_SAMA5_ADC_DMA
+static void sam_adc_dmacallback(DMA_HANDLE handle, void *arg, int result);
+static int sam_adc_dmasetup(struct sam_adc_s *priv, FAR uint8_t *buffer,
+ size_t buflen)
+#endif
+
/* ADC interrupt handling */
#ifdef SAMA5_ADC_HAVE_CHANNELS
@@ -208,6 +234,9 @@ static struct adc_dev_s g_adcdev =
****************************************************************************/
/****************************************************************************
+ * Register Operations
+ ****************************************************************************/
+/****************************************************************************
* Name: sam_adc_checkreg
*
* Description:
@@ -264,6 +293,169 @@ static bool sam_adc_checkreg(struct sam_adc_s *priv, bool wr,
#ifdef SAMA5_ADC_HAVE_CHANNELS
/****************************************************************************
+ * DMA Helpers
+ ****************************************************************************/
+/****************************************************************************
+ * Name: sam_adc_dmacallback
+ *
+ * Description:
+ * Called when HSMCI DMA completes
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SAMA5_ADC_DMA
+static void sam_adc_dmacallback(DMA_HANDLE handle, void *arg, int result)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s *)arg;
+#warning Missing logic
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_adc_dmasetup
+ *
+ * Description:
+ * Setup to perform a read DMA. If the processor supports a data cache,
+ * then this method will also make sure that the contents of the DMA memory
+ * and the data cache are coherent. For read transfers this may mean
+ * invalidating the data cache.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO device interface
+ * buffer - The memory to DMA from
+ * buflen - The size of the DMA transfer in bytes
+ *
+ * Returned Value:
+ * OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SAMA5_ADC_DMA
+static int sam_adc_dmasetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
+ size_t buflen)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s *)dev;
+ uint32_t paddr;
+ uint32_t maddr;
+
+ DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
+ DEBUGASSERT(((uint32_t)buffer & 3) == 0);
+
+ /* Physical address of the ADC LCDR register and of the buffer location in
+ * RAM.
+ */
+
+ paddr = sam_physregaddr(SAM_ADC_LCDR);
+ maddr = sam_physramaddr((uintptr_t)buffer);
+
+ /* Configure the RX DMA */
+
+ sam_dmarxsetup(priv->dma, paddr, maddr, buflen);
+
+ /* Enable DMA handshaking */
+#warning Missing logic
+
+ /* Start the DMA */
+
+ sam_dmastart(priv->dma, sam_adc_dmacallback, priv);
+
+ /* Configure DMA-related interrupts */
+#warning Missing loic
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * ADC interrupt handling
+ ****************************************************************************/
+/****************************************************************************
+ * Name: sam_adc_endconversion
+ *
+ * Description:
+ * End of conversion interrupt handler
+ *
+ ****************************************************************************/
+
+static void sam_adc_endconversion(struct sam_adc_s *priv, uint32_t pending)
+{
+ uint32_t regval;
+ int chan;
+
+ /* Check for the end of conversion event on each channel */
+
+ for (chan = 0; chan < SAM_ADC_NCHANNELS && pending != 0; chan++)
+ {
+ uint32_t bit = ADC_INT_EOC(chan);
+ if ((pending & bit) != 0)
+ {
+ /* Read the ADC sample and pass it to the upper half */
+
+ regval = sam_adc_getreg(priv, SAM_ADC_CDR(chan));
+ ret = adc_receive(&priv->dev, chan, regval & ADC_CDR_DATA_MASK);
+ pending &= ~bit;
+ }
+ }
+}
+
+#endif /* SAMA5_ADC_HAVE_CHANNELS */
+
+/****************************************************************************
+ * Name: sam_adc_interrupt
+ *
+ * Description:
+ * ADC interrupt handler
+ *
+ ****************************************************************************/
+
+static int sam_adc_interrupt(int irq, void *context)
+{
+ struct sam_adc_s *priv = (struct sam_adc_s *)g_adcdev.ad_priv;
+ uint32_t isr;
+ uint32_t imr;
+ uint32_t pending;
+ uint32_t regval;
+
+ /* Get the set of unmasked, pending ADC interrupts */
+
+ isr = sam_adc_getreg(priv, SAM_ADC_ISR);
+ imr = sam_adc_getreg(priv, SAM_ADC_IMR);
+ pending = isr & imr;
+
+ /* Handle pending touchscreen interrupts */
+
+#ifdef CONFIG_SAMA5_TOUCHSCREEN
+ if ((pending & ADC_TSD_INTS) != 0)
+ {
+ /* Let the touchscreen handle its interrupts */
+
+ sam_tsd_interrupt(pending);
+ pending &= ~ADC_TSD_INTS;
+ }
+#endif
+
+#ifdef SAMA5_ADC_HAVE_CHANNELS
+ /* Check for end-of-conversion interrupts */
+
+ if ((pending & ADC_INT_EOCALL) != 0)
+ {
+ /* Let the touchscreen handle its interrupts */
+
+ sam_adc_endconversion(pending);
+ pending &= ~ADC_INT_EOCALL;
+ }
+#endif
+
+ /* Make sure that all interrupts were handled */
+
+ DEBUGASSERT(pending == 0);
+ return OK;
+}
+
+/****************************************************************************
+ * ADC methods
+ ****************************************************************************/
+/****************************************************************************
* Name: sam_adc_reset
*
* Description:
@@ -278,6 +470,12 @@ static void sam_adc_reset(struct adc_dev_s *dev)
irqstate_t flags;
uint32_t regval;
+#ifdef CONFIG_SAMA5_ADC_DMA
+ /* Stop any ongoing DMA */
+
+ sam_dmastop(priv->dma);
+#endif
+
/* Reset the ADC controller */
flags = irqsave();
@@ -389,90 +587,6 @@ static int sam_adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg)
}
/****************************************************************************
- * Name: sam_adc_endconversion
- *
- * Description:
- * End of conversion interrupt handler
- *
- ****************************************************************************/
-
-static void sam_adc_endconversion(struct sam_adc_s *priv, uint32_t pending)
-{
- uint32_t regval;
- int chan;
-
- /* Check for the end of conversion event on each channel */
-
- for (chan = 0; chan < SAM_ADC_NCHANNELS && pending != 0; chan++)
- {
- uint32_t bit = ADC_INT_EOC(chan);
- if ((pending & bit) != 0)
- {
- /* Read the ADC sample and pass it to the upper half */
-
- regval = sam_adc_getreg(priv, SAM_ADC_CDR(chan));
- ret = adc_receive(&priv->dev, chan, regval & ADC_CDR_DATA_MASK);
- pending &= ~bit;
- }
- }
-}
-
-#endif /* SAMA5_ADC_HAVE_CHANNELS */
-
-/****************************************************************************
- * Name: sam_adc_interrupt
- *
- * Description:
- * ADC interrupt handler
- *
- ****************************************************************************/
-
-static int sam_adc_interrupt(int irq, void *context)
-{
- struct sam_adc_s *priv = (struct sam_adc_s *)g_adcdev.ad_priv;
- uint32_t regval;
- struct sam_adc_s *priv = &g_adcpriv;
- uint32_t isr;
- uint32_t imr;
- uint32_t pending;
-
- /* Get the set of unmasked, pending ADC interrupts */
-
- isr = sam_adc_getreg(priv, SAM_ADC_ISR);
- imr = sam_adc_getreg(priv, SAM_ADC_IMR);
- pending = isr & imr;
-
- /* Handle pending touchscreen interrupts */
-
-#ifdef CONFIG_SAMA5_TOUCHSCREEN
- if ((pending & ADC_TSD_INTS) != 0)
- {
- /* Let the touchscreen handle its interrupts */
-
- sam_tsd_interrupt(pending);
- pending &= ~ADC_TSD_INTS;
- }
-#endif
-
-#ifdef SAMA5_ADC_HAVE_CHANNELS
- /* Check for end-of-conversion interrupts */
-
- if ((pending & ADC_INT_EOCALL) != 0)
- {
- /* Let the touchscreen handle its interrupts */
-
- sam_adc_endconversion(pending);
- pending &= ~ADC_INT_EOCALL;
- }
-#endif
-
- /* Make sure that all interrupts were handled */
-
- DEBUGASSERT(pending == 0);
- return OK;
-}
-
-/****************************************************************************
* Public Functions
****************************************************************************/
@@ -535,6 +649,13 @@ struct adc_dev_s *sam_adc_initialize(void)
sam_configpio(PIO_ADC_TRG);
#endif
+#ifdef CONFIG_SAMA5_ADC_DMA
+ /* Allocate a DMA channel */
+
+ priv->dma = sam_dmachannel(dmac, DMA_FLAGS);
+ DEBUGASSERT(priv->dma);
+#endif
+
/* Reset the ADC controller */
sam_adc_putreg(priv, SAM_ADC_CR, ADC_CR_SWRST);
diff --git a/nuttx/arch/arm/src/sama5/sam_touchscreen.c b/nuttx/arch/arm/src/sama5/sam_touchscreen.c
index b46ed8086..3792af259 100644
--- a/nuttx/arch/arm/src/sama5/sam_touchscreen.c
+++ b/nuttx/arch/arm/src/sama5/sam_touchscreen.c
@@ -67,12 +67,12 @@
* defined here so that it will be used consistently in all places.
*/
-#define DEV_FORMAT "/dev/input%d"
-#define DEV_NAMELEN 16
+#define DEV_FORMAT "/dev/input%d"
+#define DEV_NAMELEN 16
/* Poll the pen position while the pen is down at this rate (50MS): */
-#define TSD_WDOG_DELAY ((50 + (MSEC_PER_TICK-1))/ MSEC_PER_TICK)
+#define TSD_WDOG_DELAY ((50 + (MSEC_PER_TICK-1))/ MSEC_PER_TICK)
/* This is a value for the threshold that guantees a big difference on the
* first pendown (but can't overflow).
@@ -80,13 +80,36 @@
#define INVALID_THRESHOLD 0x1000
+/* Touchscreen interrupt event sets
+ *
+ * ADC_INT_XRDY TS Measure XPOS Ready Interrupt
+ * ADC_INT_YRDY TS Measure YPOS Ready Interrupt
+ * ADC_INT_PRDY TS Measure Pressure Ready Interrupt
+ * ADC_INT_PEN Pen Contact Interrupt
+ * ADC_INT_NOPEN No Pen Contact Interrupt
+ * ADC_SR_PENS Pen detect Status (Not an interrupt)
+ */
+
+#define ADC_TSD_CMNINTS (ADC_INT_XRDY | ADC_INT_YRDY | ADC_INT_PRDY | ADC_INT_NOPEN)
+#define ADC_TSD_ALLINTS (ADC_TSD_CMNINTS | ADC_INT_PEN)
+#define ADC_TSD_ALLSTATUS (ADC_TSD_ALLINTS | ADC_INT_PENS)
+#define ADC_TSD_RELEASEINTS ADC_TSD_CMNINTS
+
+/* Data ready/pen status bit definitions */
+
+#define TSD_XREADY (1 << 0) /* X value is ready */
+#define TSD_YREADY (1 << 1) /* Y value is ready */
+#define TSD_PREADY (1 << 2) /* Pressure value is ready */
+#define TSD_PENDOWN (1 << 3) /* Pen is down */
+#define TSD_ALLREADY (TSD_XREADY | TSD_YREADY | TSD_PREADY)
+
/****************************************************************************
* Private Types
****************************************************************************/
/* This describes the state of one contact */
-enum sam_contact_3
+enum sam_contact_e
{
CONTACT_NONE = 0, /* No contact */
CONTACT_DOWN, /* First contact */
@@ -107,13 +130,15 @@ struct sam_sample_s
/* This structure describes the state of one touchscreen driver instance */
-struct sam_dev_s
+struct sam_tsd_s
{
uint8_t nwaiters; /* Number of threads waiting for touchscreen data */
uint8_t id; /* Current touch point ID */
+ uint8_t status; /* Data ready/pen status bit set */
volatile bool penchange; /* An unreported event is buffered */
uint16_t threshx; /* Thresholding X value */
uint16_t threshy; /* Thresholding Y value */
+ volatile uint32_t pending; /* Pending interrupt set set */
sem_t devsem; /* Manages exclusive access to this structure */
sem_t waitsem; /* Used to wait for the availability of data */
@@ -138,22 +163,22 @@ struct sam_dev_s
/* Interrupt bottom half logic and data sampling */
-static void sam_notify(FAR struct sam_dev_s *priv);
-static int sam_sample(FAR struct sam_dev_s *priv,
- FAR struct sam_sample_s *sample);
-static int sam_waitsample(FAR struct sam_dev_s *priv,
- FAR struct sam_sample_s *sample);
-static void sam_bottomhalf(FAR void *arg);
+static void sam_notify(struct sam_tsd_s *priv);
+static int sam_sample(struct sam_tsd_s *priv, struct sam_sample_s *sample);
+static int sam_waitsample(struct sam_tsd_s *priv,
+ struct sam_sample_s *sample);
+static void sam_bottomhalf(void *arg);
+static int sam_schedule(struct sam_tsd_s *priv, uint32_t pending);
+static void sam_wdog(int argc, uint32_t arg1, ...);
/* Character driver methods */
-static int sam_open(FAR struct file *filep);
-static int sam_close(FAR struct file *filep);
-static ssize_t sam_read(FAR struct file *filep, FAR char *buffer,
- size_t len);
-static int sam_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+static int sam_open(struct file *filep);
+static int sam_close(struct file *filep);
+static ssize_t sam_read(struct file *filep, char *buffer, size_t len);
+static int sam_ioctl(struct file *filep, int cmd, unsigned long arg);
#ifndef CONFIG_DISABLE_POLL
-static int sam_poll(FAR struct file *filep, struct pollfd *fds, bool setup);
+static int sam_poll(struct file *filep, struct pollfd *fds, bool setup);
#endif
/****************************************************************************
@@ -177,7 +202,7 @@ static const struct file_operations g_tsdops =
/* The driver state structure is pre-allocated. */
-static struct sam_dev_s g_tsd;
+static struct sam_tsd_s g_tsd;
/****************************************************************************
* Private Functions
@@ -187,7 +212,7 @@ static struct sam_dev_s g_tsd;
* Name: sam_notify
****************************************************************************/
-static void sam_notify(FAR struct sam_dev_s *priv)
+static void sam_notify(struct sam_tsd_s *priv)
{
#ifndef CONFIG_DISABLE_POLL
int i;
@@ -230,8 +255,7 @@ static void sam_notify(FAR struct sam_dev_s *priv)
* Name: sam_sample
****************************************************************************/
-static int sam_sample(FAR struct sam_dev_s *priv,
- FAR struct sam_sample_s *sample)
+static int sam_sample(struct sam_tsd_s *priv, struct sam_sample_s *sample)
{
irqstate_t flags;
int ret = -EAGAIN;
@@ -284,8 +308,7 @@ static int sam_sample(FAR struct sam_dev_s *priv,
* Name: sam_waitsample
****************************************************************************/
-static int sam_waitsample(FAR struct sam_dev_s *priv,
- FAR struct sam_sample_s *sample)
+static int sam_waitsample(struct sam_tsd_s *priv, struct sam_sample_s *sample)
{
irqstate_t flags;
int ret;
@@ -362,57 +385,28 @@ errout:
}
/****************************************************************************
- * Name: sam_schedule
- ****************************************************************************/
-
-static int sam_schedule(FAR struct sam_dev_s *priv)
-{
- int ret;
-
- /* Disable further touchscreen interrupts. Touchscreen interrupts will be
- * re-enabled after the worker thread executes.
- */
-
- sam_adc_putreg32(priv->dev, SAM_ADC_IDR, ADC_TSD_INTS);
-
- /* Disable the watchdog timer. It will be re-enabled in the worker thread
- * while the pen remains down.
- */
-
- wd_cancel(priv->wdog);
-
- /* Transfer processing to the worker thread. Since touchscreen ADC 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(HPWORK, &priv->work, sam_bottomhalf, priv, 0);
- if (ret != 0)
- {
- illdbg("Failed to queue work: %d\n", ret);
- }
-
- return OK;
-}
-
-/****************************************************************************
- * Name: sam_wdog
- ****************************************************************************/
-
-static void sam_wdog(int argc, uint32_t arg1, ...)
-{
- FAR struct sam_dev_s *priv = (FAR struct sam_dev_s *)((uintptr_t)arg1);
- (void)sam_schedule(priv);
-}
-
-/****************************************************************************
* Name: sam_bottomhalf
+ *
+ * Description:
+ * This function executes on the worker thread. It is scheduled by
+ * sam_tsd_interrupt whenever any interesting, enabled TSD event occurs.
+ * All TSD interrupts are disabled when this function runs. sam_bottomhalf
+ * will re-enable TSD interrupts when it completes processing all pending
+ * TSD events.
+ *
+ * Input Parameters
+ * arg - The touchscreen private data structure cast to (void *)
+ *
+ * Returned Value:
+ * None
+ *
****************************************************************************/
-static void sam_bottomhalf(FAR void *arg)
+static void sam_bottomhalf(void *arg)
{
- FAR struct sam_dev_s *priv = (FAR struct sam_dev_s *)arg;
+ struct sam_tsd_s *priv = (struct sam_tsd_s *)arg;
+ uint32_t pending;
+ uint32_t regval;
uint16_t x;
uint16_t y;
uint16_t xdiff;
@@ -428,6 +422,10 @@ static void sam_bottomhalf(FAR void *arg)
wd_cancel(priv->wdog);
+ /* Get the set of unmasked, pending ADC interrupts */
+
+ pending = priv->pending;
+
/* Get exclusive access to the driver data structure */
do
@@ -556,7 +554,7 @@ static void sam_bottomhalf(FAR void *arg)
ignored:
/* Re-enable touchscreen interrupts. */
- sam_adc_putreg32(priv->dev, SAM_ADC_IER, ADC_TSD_INTS);
+ sam_adc_putreg32(priv->dev, SAM_ADC_IER, ADC_TSD_ALLINTS);
/* Release our lock on the state structure */
@@ -564,10 +562,73 @@ ignored:
}
/****************************************************************************
+ * Name: sam_schedule
+ ****************************************************************************/
+
+static int sam_schedule(struct sam_tsd_s *priv, uint32_t pending)
+{
+ int ret;
+
+ /* Disable the watchdog timer. It will be re-enabled in the worker thread
+ * while the pen remains down.
+ */
+
+ wd_cancel(priv->wdog);
+
+ /* Disable further touchscreen interrupts. Touchscreen interrupts will be
+ * re-enabled after the worker thread executes.
+ */
+
+ sam_adc_putreg32(priv->dev, SAM_ADC_IDR, ADC_TSD_ALLINTS);
+
+ /* Save the set of pending interrupts for the bottom half (in case any
+ * were cleared by reading the ISR.
+ */
+
+ priv->pending = pending.
+
+ /* Transfer processing to the worker thread. Since touchscreen ADC 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(HPWORK, &priv->work, sam_bottomhalf, priv, 0);
+ if (ret != 0)
+ {
+ illdbg("Failed to queue work: %d\n", ret);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: sam_wdog
+ *
+ * Description:
+ * While the pen is pressed, pen position is periodically polled via a
+ * watchdog timer. This function handles that timer expiration.
+ *
+ ****************************************************************************/
+
+static void sam_wdog(int argc, uint32_t arg1, ...)
+{
+ struct sam_tsd_s *priv = (struct sam_tsd_s *)((uintptr_t)arg1);
+ uint32_t pending;
+
+ /* There should be no pending TSD interrupts, but we need to get the PENS
+ * status bit as a minimum.
+ */
+
+ pending = sam_adc_getreg(priv, SAM_ADC_ISR) & ADC_TSD_ALLSTATUS;
+ (void)sam_schedule(priv, pending);
+}
+
+/****************************************************************************
* Name: sam_open
****************************************************************************/
-static int sam_open(FAR struct file *filep)
+static int sam_open(struct file *filep)
{
ivdbg("Opening\n");
return OK;
@@ -577,7 +638,7 @@ static int sam_open(FAR struct file *filep)
* Name: sam_close
****************************************************************************/
-static int sam_close(FAR struct file *filep)
+static int sam_close(struct file *filep)
{
ivdbg("Closing\n");
return OK;
@@ -587,11 +648,11 @@ static int sam_close(FAR struct file *filep)
* Name: sam_read
****************************************************************************/
-static ssize_t sam_read(FAR struct file *filep, FAR char *buffer, size_t len)
+static ssize_t sam_read(struct file *filep, char *buffer, size_t len)
{
- FAR struct inode *inode;
- FAR struct sam_dev_s *priv;
- FAR struct touch_sample_s *report;
+ struct inode *inode;
+ struct sam_tsd_s *priv;
+ struct touch_sample_s *report;
struct sam_sample_s sample;
int ret;
@@ -600,7 +661,7 @@ static ssize_t sam_read(FAR struct file *filep, FAR char *buffer, size_t len)
inode = filep->f_inode;
DEBUGASSERT(inode && inode->i_private);
- priv = (FAR struct sam_dev_s *)inode->i_private;
+ priv = (struct sam_tsd_s *)inode->i_private;
/* Verify that the caller has provided a buffer large enough to receive
* the touch data.
@@ -661,12 +722,12 @@ static ssize_t sam_read(FAR struct file *filep, FAR char *buffer, size_t len)
* to the caller.
*/
- report = (FAR struct touch_sample_s *)buffer;
+ report = (struct touch_sample_s *)buffer;
memset(report, 0, SIZEOF_TOUCH_SAMPLE_S(1));
- report->npoints = 1;
- report->point[0].id = sample.id;
- report->point[0].x = sample.x;
- report->point[0].y = sample.y;
+ report->npoints = 1;
+ report->point[0].id = sample.id;
+ report->point[0].x = sample.x;
+ report->point[0].y = sample.y;
/* Report the appropriate flags */
@@ -716,18 +777,18 @@ errout:
* Name:sam_ioctl
****************************************************************************/
-static int sam_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+static int sam_ioctl(struct file *filep, int cmd, unsigned long arg)
{
- FAR struct inode *inode;
- FAR struct sam_dev_s *priv;
- int ret;
+ struct inode *inode;
+ struct sam_tsd_s *priv;
+ int ret;
ivdbg("cmd: %d arg: %ld\n", cmd, arg);
DEBUGASSERT(filep);
inode = filep->f_inode;
DEBUGASSERT(inode && inode->i_private);
- priv = (FAR struct sam_dev_s *)inode->i_private;
+ priv = (struct sam_tsd_s *)inode->i_private;
/* Get exclusive access to the driver data structure */
@@ -758,20 +819,19 @@ static int sam_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
****************************************************************************/
#ifndef CONFIG_DISABLE_POLL
-static int sam_poll(FAR struct file *filep, FAR struct pollfd *fds,
- bool setup)
+static int sam_poll(struct file *filep, struct pollfd *fds, bool setup)
{
- FAR struct inode *inode;
- FAR struct sam_dev_s *priv;
- int ret = OK;
- int i;
+ struct inode *inode;
+ struct sam_tsd_s *priv;
+ int ret = OK;
+ int i;
ivdbg("setup: %d\n", (int)setup);
DEBUGASSERT(filep && fds);
inode = filep->f_inode;
DEBUGASSERT(inode && inode->i_private);
- priv = (FAR struct sam_dev_s *)inode->i_private;
+ priv = (struct sam_tsd_s *)inode->i_private;
/* Are we setting up the poll? Or tearing it down? */
@@ -871,7 +931,7 @@ errout:
int sam_tsd_register(struct adc_dev_s *dev, int minor)
{
- struct sam_dev_s *priv = &g_tsd;
+ struct sam_tsd_s *priv = &g_tsd;
char devname[DEV_NAMELEN];
int ret;
@@ -883,7 +943,7 @@ int sam_tsd_register(struct adc_dev_s *dev, int minor)
/* Initialize the touchscreen device driver instance */
- memset(priv, 0, sizeof(struct sam_dev_s));
+ memset(priv, 0, sizeof(struct sam_tsd_s));
priv->dev = dev; /* Save the ADC device handle */
priv->wdog = wd_create(); /* Create a watchdog timer */
priv->threshx = INVALID_THRESHOLD; /* Initialize thresholding logic */
@@ -941,29 +1001,43 @@ errout_with_priv:
* Handles ADC interrupts associated with touchscreen channels
*
* Input parmeters:
- * None
+ * pending - Current set of pending interrupts being handled
*
* Returned Value:
* None
*
****************************************************************************/
-void sam_tsd_interrupt(void)
+void sam_tsd_interrupt(uint32_t pending)
{
- struct sam_dev_s *priv = &g_tsd;
+ struct sam_tsd_s *priv = &g_tsd;
int ret;
- /* Disable further touchscreen interrupts */
+ /* Are there pending TSD interrupts? */
+
+ if ((pending & ADC_TSD_ALLINTS) != 0)
+ {
+ /* Disable further touchscreen interrupts */
- sam_adc_putreg32(priv->dev, SAM_ADC_IDR, ADC_TSD_INTS);
+ sam_adc_putreg32(priv->dev, SAM_ADC_IDR, ADC_TSD_ALLINTS);
- /* Schedule sampling to occur on the worker thread */
+ /* Save the set of pending interrupts for the bottom half (in case any
+ * were cleared by reading the ISR.
+ */
- ret = sam_schedule(priv);
- if (ret < 0)
- {
- idbg("ERROR: sam_schedule failed: %d\n", ret);
+ priv->pending = pending & ADC_TSD_ALLSTATUS;
+
+ /* Schedule sampling to occur by the interrupt bottom half on the
+ * worker thread.
+ */
+
+ ret = sam_schedule(priv, pending);
+ if (ret < 0)
+ {
+ idbg("ERROR: sam_schedule failed: %d\n", ret);
+ }
}
+
return ret;
}