From ede78e57dc5070c8e58cdf08f3296d5182c63ef9 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 30 Sep 2013 14:28:42 -0600 Subject: SAMA5 ADC/Touchscreen: A little more progress. Still not complete --- nuttx/arch/arm/src/sama5/chip/sam_adc.h | 2 + nuttx/arch/arm/src/sama5/sam_adc.c | 345 ++++++++++++++++++++++------- nuttx/arch/arm/src/sama5/sam_adc.h | 63 ++++++ nuttx/arch/arm/src/sama5/sam_touchscreen.c | 57 ++--- nuttx/arch/arm/src/sama5/sam_touchscreen.h | 11 +- nuttx/include/nuttx/analog/adc.h | 2 +- 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 * @@ -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,13 +381,44 @@ 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 */ return -ENOTTY; } +/**************************************************************************** + * 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 * @@ -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' -- cgit v1.2.3