summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-09-30 14:28:42 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-09-30 14:28:42 -0600
commitede78e57dc5070c8e58cdf08f3296d5182c63ef9 (patch)
tree4928e99758c47341828e3450249cf40fb4caaf90
parent9f2b12c2529e0fbe02693c35a82bd35168637c23 (diff)
downloadnuttx-ede78e57dc5070c8e58cdf08f3296d5182c63ef9.tar.gz
nuttx-ede78e57dc5070c8e58cdf08f3296d5182c63ef9.tar.bz2
nuttx-ede78e57dc5070c8e58cdf08f3296d5182c63ef9.zip
SAMA5 ADC/Touchscreen: A little more progress. Still not complete
-rw-r--r--nuttx/arch/arm/src/sama5/chip/sam_adc.h2
-rw-r--r--nuttx/arch/arm/src/sama5/sam_adc.c345
-rw-r--r--nuttx/arch/arm/src/sama5/sam_adc.h63
-rw-r--r--nuttx/arch/arm/src/sama5/sam_touchscreen.c57
-rw-r--r--nuttx/arch/arm/src/sama5/sam_touchscreen.h11
-rw-r--r--nuttx/include/nuttx/analog/adc.h2
6 files changed, 368 insertions, 112 deletions
diff --git a/nuttx/arch/arm/src/sama5/chip/sam_adc.h b/nuttx/arch/arm/src/sama5/chip/sam_adc.h
index b722533c4..1755b1f58 100644
--- a/nuttx/arch/arm/src/sama5/chip/sam_adc.h
+++ b/nuttx/arch/arm/src/sama5/chip/sam_adc.h
@@ -289,6 +289,8 @@
#define ADC_INT_EOC7 (1 << 9) /* Bit 9: End of Conversion 9 */
#define ADC_INT_EOC7 (1 << 10) /* Bit 10: End of Conversion 10 */
#define ADC_INT_EOC7 (1 << 11) /* Bit 11: End of Conversion 11 */
+#define ADC_INT_EOCALL (0x00000fff)
+
#define ADC_INT_XRDY (1 << 20) /* Bit 20: TS Measure XPOS Ready Interrupt */
#define ADC_INT_YRDY (1 << 21) /* Bit 21: TS Measure YPOS Ready Interrupt */
#define ADC_INT_PRDY (1 << 22) /* Bit 22: TS Measure Pressure Ready Interrupt */
diff --git a/nuttx/arch/arm/src/sama5/sam_adc.c b/nuttx/arch/arm/src/sama5/sam_adc.c
index 4249a44ab..d8b58010d 100644
--- a/nuttx/arch/arm/src/sama5/sam_adc.c
+++ b/nuttx/arch/arm/src/sama5/sam_adc.c
@@ -1,7 +1,6 @@
/************************************************************************************
* arch/arm/src/sama5/sam_adc.c
*
- *
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
@@ -65,6 +64,64 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+/* Get the set of channel interrupts to enable */
+
+#define SAMA5_CHAN0_ENABLE 0
+#define SAMA5_CHAN1_ENABLE 0
+#define SAMA5_CHAN2_ENABLE 0
+#define SAMA5_CHAN3_ENABLE 0
+#define SAMA5_CHAN4_ENABLE 0
+#define SAMA5_CHAN5_ENABLE 0
+#define SAMA5_CHAN6_ENABLE 0
+#define SAMA5_CHAN7_ENABLE 0
+#define SAMA5_CHAN8_ENABLE 0
+#define SAMA5_CHAN9_ENABLE 0
+#define SAMA5_CHAN10_ENABLE 0
+#define SAMA5_CHAN11_ENABLE 0
+
+#if defined(CONFIG_SAMA5_ADC_CHAN0)
+# undef SAMA5_CHAN0_ENABLE
+# define SAMA5_CHAN0_ENABLE ADC_INT_EOC0
+#elif defined(CONFIG_SAMA5_ADC_CHAN1)
+# undef SAMA5_CHAN1_ENABLE
+# define SAMA5_CHAN1_ENABLE ADC_INT_EOC1
+#elif defined(CONFIG_SAMA5_ADC_CHAN2)
+# undef SAMA5_CHAN2_ENABLE
+# define SAMA5_CHAN2_ENABLE ADC_INT_EOC2
+#elif defined(CONFIG_SAMA5_ADC_CHAN3)
+# undef SAMA5_CHAN3_ENABLE
+# define SAMA5_CHAN3_ENABLE ADC_INT_EOC3
+#elif defined(CONFIG_SAMA5_ADC_CHAN4)
+# undef SAMA5_CHAN4_ENABLE
+# define SAMA5_CHAN4_ENABLE ADC_INT_EOC4
+#elif defined(CONFIG_SAMA5_ADC_CHAN5)
+# undef SAMA5_CHAN5_ENABLE
+# define SAMA5_CHAN5_ENABLE ADC_INT_EOC5
+#elif defined(CONFIG_SAMA5_ADC_CHAN6)
+# undef SAMA5_CHAN6_ENABLE
+# define SAMA5_CHAN6_ENABLE ADC_INT_EOC6
+#elif defined(CONFIG_SAMA5_ADC_CHAN7)
+# undef SAMA5_CHAN7_ENABLE
+# define SAMA5_CHAN7_ENABLE ADC_INT_EOC7
+#elif defined(CONFIG_SAMA5_ADC_CHAN8)
+# undef SAMA5_CHAN8_ENABLE
+# define SAMA5_CHAN8_ENABLE ADC_INT_EOC8
+#elif defined(CONFIG_SAMA5_ADC_CHAN9)
+# undef SAMA5_CHAN9_ENABLE
+# define SAMA5_CHAN9_ENABLE ADC_INT_EOC9
+#elif defined(CONFIG_SAMA5_ADC_CHAN10)
+# undef SAMA5_CHAN10_ENABLE
+# define SAMA5_CHAN10_ENABLE ADC_INT_EOC10
+#elif defined(CONFIG_SAMA5_ADC_CHAN11)
+# undef SAMA5_CHAN11_ENABLE
+# define SAMA5_CHAN11_ENABLE ADC_INT_EOC11
+#endif
+
+#define SAMA5_CHAN_ENABLE \
+ (SAMA5_CHAN0_ENABLE || SAMA5_CHAN1_ENABLE || SAMA5_CHAN2_ENABLE || \
+ SAMA5_CHAN3_ENABLE || SAMA5_CHAN4_ENABLE || SAMA5_CHAN5_ENABLE || \
+ SAMA5_CHAN6_ENABLE || SAMA5_CHAN7_ENABLE || SAMA5_CHAN8_ENABLE || \
+ SAMA5_CHAN9_ENABLE || SAMA5_CHAN10_ENABLE || SAMA5_CHAN11_ENABLE)
/****************************************************************************
* Private Types
@@ -74,13 +131,17 @@
struct sam_adc_s
{
+#ifdef SAMA5_ADC_HAVE_CHANNELS
+ struct adc_dev_s dev; /* The external via of the ADC device */
+#endif
+
/* Debug stuff */
#ifdef CONFIG_SAMA5_ADC_REGDEBUG
- bool wrlast; /* Last was a write */
- uintptr_t addrlast; /* Last address */
- uint32_t vallast; /* Last value */
- int ntimes; /* Number of times */
+ bool wrlast; /* Last was a write */
+ uintptr_t addrlast; /* Last address */
+ uint32_t vallast; /* Last value */
+ int ntimes; /* Number of times */
#endif
};
@@ -90,31 +151,32 @@ struct sam_adc_s
/* Register operations ******************************************************/
#if defined(CONFIG_SAMA5_ADC_REGDEBUG) && defined(CONFIG_DEBUG)
-static bool sam_adc_checkreg(struct sam_gmac_s *priv, bool wr,
- uint32_t regval, uintptr_t address);
-static uint32_t sam_adc_getreg(struct sam_gmac_s *priv, uintptr_t addr);
-static void sam_adc_putreg(struct sam_gmac_s *priv, uintptr_t addr, uint32_t val);
-#else
-# define sam_adc_getreg(priv,addr) getreg32(addr)
-# define sam_adc_putreg(priv,addr,val) putreg32(val,addr)
+static bool sam_adc_checkreg(struct sam_adc_s *priv, bool wr,
+ uint32_t regval, uintptr_t address);
#endif
/* ADC interrupt handling */
+#ifdef SAMA5_ADC_HAVE_CHANNELS
+static void sam_adc_endconversion(struct sam_adc_s *priv, uint32_t pending);
+#endif
static int sam_adc_interrupt(int irq, void *context);
/* ADC methods */
-static void sam_adc_reset(FAR struct adc_dev_s *dev);
-static int sam_adc_setup(FAR struct adc_dev_s *dev);
-static void sam_adc_shutdown(FAR struct adc_dev_s *dev);
-static void sam_adc_rxint(FAR struct adc_dev_s *dev, bool enable);
-static int sam_adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg);
+#ifdef SAMA5_ADC_HAVE_CHANNELS
+static void sam_adc_reset(struct adc_dev_s *dev);
+static int sam_adc_setup(struct adc_dev_s *dev);
+static void sam_adc_shutdown(struct adc_dev_s *dev);
+static void sam_adc_rxint(struct adc_dev_s *dev, bool enable);
+static int sam_adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg);
+#endif
/****************************************************************************
* Private Data
****************************************************************************/
+#ifdef SAMA5_ADC_HAVE_CHANNELS
/* ADC lower half device operations */
static const struct adc_ops_s g_adcops =
@@ -125,20 +187,21 @@ static const struct adc_ops_s g_adcops =
.ao_rxint = sam_adc_rxint,
.ao_ioctl = sam_adc_ioctl,
};
+#endif
/* ADC internal state */
-static struct sam_adc_s g_adcpriv =
-{
-};
+static struct sam_adc_s g_adcpriv;
+#ifdef SAMA5_ADC_HAVE_CHANNELS
/* ADC device instance */
static struct adc_dev_s g_adcdev =
{
.ad_ops = &g_adcops,
- .ad_priv = &g_adcpriv,
+ .ad_priv = &g_adcpriv.dev,
};
+#endif
/****************************************************************************
* Private Functions
@@ -161,7 +224,7 @@ static struct adc_dev_s g_adcdev =
****************************************************************************/
#ifdef CONFIG_SAMA5_ADC_REGDEBUG
-static bool sam_adc_checkreg(struct sam_gmac_s *priv, bool wr,
+static bool sam_adc_checkreg(struct sam_adc_s *priv, bool wr,
uint32_t regval, uintptr_t address)
{
if (wr == priv->wrlast && /* Same kind of access? */
@@ -198,48 +261,7 @@ static bool sam_adc_checkreg(struct sam_gmac_s *priv, bool wr,
}
#endif
-/****************************************************************************
- * Name: sam_adc_getreg
- *
- * Description:
- * Read any 32-bit register using an absolute address.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SAMA5_ADC_REGDEBUG
-static uint32_t sam_adc_getreg(struct sam_gmac_s *priv, uintptr_t address)
-{
- uint32_t regval = getreg32(address);
-
- if (sam_adc_checkreg(priv, false, regval, address))
- {
- lldbg("%08x->%08x\n", address, regval);
- }
-
- return regval;
-}
-#endif
-
-/****************************************************************************
- * Name: sam_adc_putreg
- *
- * Description:
- * Write to any 32-bit register using an absolute address.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_SAMA5_ADC_REGDEBUG
-static void sam_adc_putreg(struct sam_gmac_s *priv, uintptr_t address,
- uint32_t regval)
-{
- if (sam_adc_checkreg(priv, true, regval, address))
- {
- lldbg("%08x<-%08x\n", address, regval);
- }
-
- putreg32(regval, address);
-}
-#endif
+#ifdef SAMA5_ADC_HAVE_CHANNELS
/****************************************************************************
* Name: sam_adc_reset
@@ -250,15 +272,20 @@ static void sam_adc_putreg(struct sam_gmac_s *priv, uintptr_t address,
*
****************************************************************************/
-static void sam_adc_reset(FAR struct adc_dev_s *dev)
+static void sam_adc_reset(struct adc_dev_s *dev)
{
- FAR struct sam_adc_s *priv = (FAR struct sam_adc_s *)dev->ad_priv;
+ struct sam_adc_s *priv = (struct sam_adc_s *)dev->ad_priv;
irqstate_t flags;
uint32_t regval;
+ /* Reset the ADC controller */
+
flags = irqsave();
-#warning Missing logic
+ sam_adc_putreg(priv, SAM_ADC_CR, ADC_CR_SWRST);
+
+ /* Reset Mode Register */
+ sam_adc_putreg(priv, SAM_ADC_MR, 0);
irqrestore(flags);
}
@@ -273,9 +300,9 @@ static void sam_adc_reset(FAR struct adc_dev_s *dev)
*
****************************************************************************/
-static int sam_adc_setup(FAR struct adc_dev_s *dev)
+static int sam_adc_setup(struct adc_dev_s *dev)
{
- FAR struct sam_adc_s *priv = (FAR struct sam_adc_s *)dev->ad_priv;
+ struct sam_adc_s *priv = (struct sam_adc_s *)dev->ad_priv;
int ret;
/* Attach the ADC interrupt */
@@ -302,15 +329,15 @@ static int sam_adc_setup(FAR struct adc_dev_s *dev)
*
****************************************************************************/
-static void sam_adc_shutdown(FAR struct adc_dev_s *dev)
+static void sam_adc_shutdown(struct adc_dev_s *dev)
{
- FAR struct sam_adc_s *priv = (FAR struct sam_adc_s *)dev->ad_priv;
+ struct sam_adc_s *priv = (struct sam_adc_s *)dev->ad_priv;
/* Disable ADC interrupts, both at the level of the ADC device and at the
* level of the NVIC.
*/
-#warning Missing logic
+ sam_adc_putreg32(priv, SAM_ADC_IDR, ADC_TSD_INTS);
up_disable_irq(SAM_IRQ_ADC);
/* Then detach the ADC interrupt handler. */
@@ -326,18 +353,23 @@ static void sam_adc_shutdown(FAR struct adc_dev_s *dev)
*
****************************************************************************/
-static void sam_adc_rxint(FAR struct adc_dev_s *dev, bool enable)
+static void sam_adc_rxint(struct adc_dev_s *dev, bool enable)
{
- FAR struct sam_adc_s *priv = (FAR struct sam_adc_s *)dev->ad_priv;
+ struct sam_adc_s *priv = (struct sam_adc_s *)dev->ad_priv;
/* Are we enabling or disabling? */
+
if (enable)
{
-#warning Missing logic
+ /* Enable channel interrupts */
+
+ sam_adc_putreg32(priv, SAM_ADC_IER, SAMA5_CHAN_ENABLE);
}
else
{
-#warning Missing logic
+ /* Disable channel interrupts */
+
+ sam_adc_putreg32(priv, SAM_ADC_IDR, ADC_INT_EOCALL);
}
}
@@ -349,7 +381,7 @@ static void sam_adc_rxint(FAR struct adc_dev_s *dev, bool enable)
*
****************************************************************************/
-static int sam_adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
+static int sam_adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg)
{
/* No ioctl commands supported */
@@ -357,6 +389,37 @@ static int sam_adc_ioctl(FAR 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:
@@ -366,11 +429,46 @@ static int sam_adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
static int sam_adc_interrupt(int irq, void *context)
{
- FAR struct sam_adc_s *priv = (FAR struct sam_adc_s *)g_adcdev.ad_priv;
+ 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;
-#warning Missing logic
+ /* 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;
}
@@ -389,12 +487,54 @@ static int sam_adc_interrupt(int irq, void *context)
*
****************************************************************************/
-FAR struct adc_dev_s *sam_adc_initialize(void)
+struct adc_dev_s *sam_adc_initialize(void)
{
/* Enable the ADC peripheral clock*/
sam_adc_enableclk();
+ /* Configure ADC pins */
+
+#ifdef CONFIG_SAMA5_ADC_CHAN0
+ sam_configpio(PIO_ADC_AD0);
+#endif
+#ifdef CONFIG_SAMA5_ADC_CHAN1
+ sam_configpio(PIO_ADC_AD1);
+#endif
+#ifdef CONFIG_SAMA5_ADC_CHAN2
+ sam_configpio(PIO_ADC_AD2);
+#endif
+#ifdef CONFIG_SAMA5_ADC_CHAN3
+ sam_configpio(PIO_ADC_AD3);
+#endif
+#ifdef CONFIG_SAMA5_ADC_CHAN4
+ sam_configpio(PIO_ADC_AD4);
+#endif
+#ifdef CONFIG_SAMA5_ADC_CHAN5
+ sam_configpio(PIO_ADC_AD5);
+#endif
+#ifdef CONFIG_SAMA5_ADC_CHAN6
+ sam_configpio(PIO_ADC_AD6);
+#endif
+#ifdef CONFIG_SAMA5_ADC_CHAN7
+ sam_configpio(PIO_ADC_AD7);
+#endif
+#ifdef CONFIG_SAMA5_ADC_CHAN8
+ sam_configpio(PIO_ADC_AD8);
+#endif
+#ifdef CONFIG_SAMA5_ADC_CHAN9
+ sam_configpio(PIO_ADC_AD9);
+#endif
+#ifdef CONFIG_SAMA5_ADC_CHAN10
+ sam_configpio(PIO_ADC_AD10);
+#endif
+#ifdef CONFIG_SAMA5_ADC_CHAN11
+ sam_configpio(PIO_ADC_AD11);
+#endif
+#if 0
+ sam_configpio(PIO_ADC_TRG);
+#endif
+
/* Reset the ADC controller */
sam_adc_putreg(priv, SAM_ADC_CR, ADC_CR_SWRST);
@@ -408,4 +548,49 @@ FAR struct adc_dev_s *sam_adc_initialize(void)
return &g_adcdev;
}
+/****************************************************************************
+ * Name: sam_adc_getreg
+ *
+ * Description:
+ * Read any 32-bit register using an absolute address.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SAMA5_ADC_REGDEBUG
+static uint32_t sam_adc_getreg(ADC_HANDLE handle, uintptr_t address)
+{
+ struct sam_adc_s *priv = (struct sam_adc_s *)handle;
+ uint32_t regval = getreg32(address);
+
+ if (sam_adc_checkreg(priv, false, regval, address))
+ {
+ lldbg("%08x->%08x\n", address, regval);
+ }
+
+ return regval;
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_adc_putreg
+ *
+ * Description:
+ * Write to any 32-bit register using an absolute address.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SAMA5_ADC_REGDEBUG
+void sam_adc_putreg(ADC_HANDLE handle, uintptr_t address, uint32_t regval)
+{
+ struct sam_adc_s *priv = (struct sam_adc_s *)handle;
+
+ if (sam_adc_checkreg(priv, true, regval, address))
+ {
+ lldbg("%08x<-%08x\n", address, regval);
+ }
+
+ putreg32(regval, address);
+}
+#endif
+
#endif /* CONFIG_SAMA5_ADC */
diff --git a/nuttx/arch/arm/src/sama5/sam_adc.h b/nuttx/arch/arm/src/sama5/sam_adc.h
index 8309c624c..803086ec2 100644
--- a/nuttx/arch/arm/src/sama5/sam_adc.h
+++ b/nuttx/arch/arm/src/sama5/sam_adc.h
@@ -50,6 +50,40 @@
****************************************************************************/
/* Configuration ************************************************************/
+#ifndef CONFIG_DEBUG
+# undef CONFIG_SAMA5_ADC_REGDEBUG
+#endif
+
+/* ADC channels 0-3 or 0-4 are not available to the ADC driver if touchscreen
+ * support is enabled.
+ */
+
+#ifdef CONFIG_SAMA5_TOUCHSCREEN
+# undef CONFIG_SAMA5_ADC_CHAN0
+# undef CONFIG_SAMA5_ADC_CHAN1
+# undef CONFIG_SAMA5_ADC_CHAN2
+# undef CONFIG_SAMA5_ADC_CHAN3
+# ifdef CONFIG_SAMA5_TOUCHSCREEN_5WIRE
+# undef CONFIG_SAMA5_ADC_CHAN4
+# endif
+#endif
+
+/* Do we have any ADC channels enabled? If not, then the ADC driver may
+ * still need to exist to support the touchscreen.
+ */
+
+#undef SAMA5_ADC_HAVE_CHANNELS
+#if defined(CONFIG_SAMA5_ADC_CHAN0) || defined(CONFIG_SAMA5_ADC_CHAN1) || \
+ defined(CONFIG_SAMA5_ADC_CHAN2) || defined(CONFIG_SAMA5_ADC_CHAN3) || \
+ defined(CONFIG_SAMA5_ADC_CHAN4) || defined(CONFIG_SAMA5_ADC_CHAN5) || \
+ defined(CONFIG_SAMA5_ADC_CHAN6) || defined(CONFIG_SAMA5_ADC_CHAN7) || \
+ defined(CONFIG_SAMA5_ADC_CHAN8) || defined(CONFIG_SAMA5_ADC_CHAN9) || \
+ defined(CONFIG_SAMA5_ADC_CHAN10) || defined(CONFIG_SAMA5_ADC_CHAN11)
+# define SAMA5_ADC_HAVE_CHANNELS 1
+#elif !defined(CONFIG_SAMA5_TOUCHSCREEN)
+# error "No ADC channels nor touchscreen"
+#endif
+
/****************************************************************************
* Public Types
****************************************************************************/
@@ -88,6 +122,35 @@ FAR struct adc_dev_s *sam_adcinitialize(void);
* Interfaces exported from the ADC to the touchscreen driver
****************************************************************************/
+/****************************************************************************
+ * Name: sam_adc_getreg
+ *
+ * Description:
+ * Read any 32-bit register using an absolute address.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SAMA5_ADC_REGDEBUG
+uint32_t sam_adc_getreg(FAR struct adc_dev_s *, uintptr_t address)
+#else
+# define sam_adc_getreg(handle,addr) getreg32(addr)
+#endif
+
+/****************************************************************************
+ * Name: sam_adc_putreg
+ *
+ * Description:
+ * Write to any 32-bit register using an absolute address.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SAMA5_ADC_REGDEBUG
+void sam_adc_putreg(FAR struct adc_dev_s *dev, uintptr_t address,
+ uint32_t regval)
+#else
+# define sam_adc_putreg(handle,addr,val) putreg32(val,addr)
+#endif
+
#undef EXTERN
#ifdef __cplusplus
}
diff --git a/nuttx/arch/arm/src/sama5/sam_touchscreen.c b/nuttx/arch/arm/src/sama5/sam_touchscreen.c
index 3dcdac21f..b46ed8086 100644
--- a/nuttx/arch/arm/src/sama5/sam_touchscreen.c
+++ b/nuttx/arch/arm/src/sama5/sam_touchscreen.c
@@ -94,7 +94,7 @@ enum sam_contact_3
CONTACT_UP, /* Contact lost */
};
-/* This structure describes the results of one ADS7843E sample */
+/* This structure describes the results of one touchscreen sample */
struct sam_sample_s
{
@@ -105,11 +105,11 @@ struct sam_sample_s
uint16_t y; /* Measured Y position */
};
-/* This structure describes the state of one ADS7843E driver instance */
+/* This structure describes the state of one touchscreen driver instance */
struct sam_dev_s
{
- uint8_t nwaiters; /* Number of threads waiting for ADS7843E data */
+ uint8_t nwaiters; /* Number of threads waiting for touchscreen data */
uint8_t id; /* Current touch point ID */
volatile bool penchange; /* An unreported event is buffered */
uint16_t threshx; /* Thresholding X value */
@@ -117,6 +117,7 @@ struct sam_dev_s
sem_t devsem; /* Manages exclusive access to this structure */
sem_t waitsem; /* Used to wait for the availability of data */
+ struct adc_dev_s *dev; /* ADC device handle */
struct work_s work; /* Supports the interrupt handling "bottom half" */
struct sam_sample_s sample; /* Last sampled touch point data */
WDOG_ID wdog; /* Poll the position while the pen is down */
@@ -127,7 +128,7 @@ struct sam_dev_s
*/
#ifndef CONFIG_DISABLE_POLL
- struct pollfd *fds[CONFIG_ADS7843E_NPOLLWAITERS];
+ struct pollfd *fds[CONFIG_SAMA5_TSD_NPOLLWAITERS];
#endif
};
@@ -198,14 +199,14 @@ static void sam_notify(FAR struct sam_dev_s *priv)
if (priv->nwaiters > 0)
{
- /* After posting this semaphore, we need to exit because the ADS7843E
+ /* After posting this semaphore, we need to exit because the touchscreen
* is no longer available.
*/
sem_post(&priv->waitsem);
}
- /* If there are threads waiting on poll() for ADS7843E data to become available,
+ /* If there are threads waiting on poll() for touchscreen data to become available,
* 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.
@@ -242,7 +243,7 @@ static int sam_sample(FAR struct sam_dev_s *priv,
flags = irqsave();
- /* Is there new ADS7843E sample data available? */
+ /* Is there new touchscreen sample data available? */
if (priv->penchange)
{
@@ -368,10 +369,11 @@ static int sam_schedule(FAR struct sam_dev_s *priv)
{
int ret;
- /* Disable further interrupts. touchscreen ADC interrupts will be re-enabled
- * after the worker thread executes.
+ /* Disable further touchscreen interrupts. Touchscreen interrupts will be
+ * re-enabled after the worker thread executes.
*/
-#warning "Missing logic"
+
+ 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.
@@ -545,19 +547,16 @@ static void sam_bottomhalf(FAR void *arg)
priv->sample.id = priv->id;
priv->penchange = true;
- /* Notify any waiters that new ADS7843E data is available */
+ /* Notify any waiters that new touchscreen data is available */
sam_notify(priv);
- /* Exit, re-enabling ADS7843E interrupts */
+ /* Exit, re-enabling touchscreen interrupts */
ignored:
+ /* Re-enable touchscreen interrupts. */
- /* Re-enable the PENIRQ interrupts */
-#warning Missing logic
-
- /* Re-enable the PENIRQ interrupt at the MCU's interrupt controller */
-#warning Missing logic
+ sam_adc_putreg32(priv->dev, SAM_ADC_IER, ADC_TSD_INTS);
/* Release our lock on the state structure */
@@ -658,7 +657,7 @@ static ssize_t sam_read(FAR struct file *filep, FAR char *buffer, size_t len)
}
}
- /* In any event, we now have sampled ADS7843E data that we can report
+ /* In any event, we now have sampled touchscreen data that we can report
* to the caller.
*/
@@ -870,9 +869,9 @@ errout:
*
****************************************************************************/
-int sam_tsd_register(int minor)
+int sam_tsd_register(struct adc_dev_s *dev, int minor)
{
- FAR struct sam_dev_s *priv = &g_tsd;
+ struct sam_dev_s *priv = &g_tsd;
char devname[DEV_NAMELEN];
int ret;
@@ -880,11 +879,12 @@ int sam_tsd_register(int minor)
/* Debug-only sanity checks */
- DEBUGASSERT(minor >= 0 && minor < 100);
+ DEBUGASSERT(dev && minor >= 0 && minor < 100);
/* Initialize the touchscreen device driver instance */
memset(priv, 0, sizeof(struct sam_dev_s));
+ priv->dev = dev; /* Save the ADC device handle */
priv->wdog = wd_create(); /* Create a watchdog timer */
priv->threshx = INVALID_THRESHOLD; /* Initialize thresholding logic */
priv->threshy = INVALID_THRESHOLD; /* Initialize thresholding logic */
@@ -945,20 +945,25 @@ errout_with_priv:
*
* Returned Value:
* None
- *
+ *
****************************************************************************/
void sam_tsd_interrupt(void)
{
- FAR struct sam_dev_s *priv = &g_tsd;
+ struct sam_dev_s *priv = &g_tsd;
int ret;
+ /* Disable further touchscreen interrupts */
+
+ sam_adc_putreg32(priv->dev, SAM_ADC_IDR, ADC_TSD_INTS);
+
/* Schedule sampling to occur on the worker thread */
ret = sam_schedule(priv);
-
- /* Clear any pending interrupts and return success */
-#warning Missing logic
+ if (ret < 0)
+ {
+ idbg("ERROR: sam_schedule failed: %d\n", ret);
+ }
return ret;
}
diff --git a/nuttx/arch/arm/src/sama5/sam_touchscreen.h b/nuttx/arch/arm/src/sama5/sam_touchscreen.h
index 8a68f2206..eebf32a93 100644
--- a/nuttx/arch/arm/src/sama5/sam_touchscreen.h
+++ b/nuttx/arch/arm/src/sama5/sam_touchscreen.h
@@ -79,7 +79,8 @@ extern "C"
* /dev/inputN where N is the minor device number
*
* Input Parameters:
- * minor - The input device minor number
+ * dev - The ADC device handle received from sam_adc_initialize()
+ * minor - The input device minor number
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
@@ -87,7 +88,7 @@ extern "C"
*
****************************************************************************/
-int sam_tsd_register(int minor);
+int sam_tsd_register(FAR struct adc_dev_s *dev, int minor);
/****************************************************************************
* Interfaces exported from the touchscreen to the ADC driver
@@ -99,14 +100,14 @@ int sam_tsd_register(int minor);
* 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);
#undef EXTERN
#ifdef __cplusplus
diff --git a/nuttx/include/nuttx/analog/adc.h b/nuttx/include/nuttx/analog/adc.h
index fe5eb9809..9970f4723 100644
--- a/nuttx/include/nuttx/analog/adc.h
+++ b/nuttx/include/nuttx/analog/adc.h
@@ -129,7 +129,7 @@ struct adc_ops_s
};
/* This is the device structure used by the driver. The caller of
- * can_register() must allocate and initialize this structure. The
+ * adc_register() must allocate and initialize this structure. The
* calling logic need only set all fields to zero except:
*
* The elements of 'ad_ops', and 'ad_priv'