SAMA5 ADC/Touchscreen: A little more progress. Still not complete
This commit is contained in:
parent
647aff0ded
commit
4cecf0b618
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
flags = irqsave();
|
||||
#warning Missing logic
|
||||
/* Reset the ADC controller */
|
||||
|
||||
flags = irqsave();
|
||||
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;
|
||||
|
||||
#warning Missing logic
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
Loading…
Reference in New Issue
Block a user