SAMA5 touchscreen and ADC: A little more progress

This commit is contained in:
Gregory Nutt
2013-10-01 11:23:24 -06:00
parent f71435780a
commit a737c93ea2
3 changed files with 388 additions and 193 deletions
+1 -1
View File
@@ -5683,7 +5683,7 @@
no serial driver) (from Alan Carvalho de Assis, 2013-9-30). no serial driver) (from Alan Carvalho de Assis, 2013-9-30).
* configs/freedom-kl25z/minnsh: A new configuration that is * configs/freedom-kl25z/minnsh: A new configuration that is
an experiement to see how small we can get the NuttX footprint. 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 * net/net_sendfile: The high performance sendfile logic is
now functional. From Max Holtzberg (2013-9-30). now functional. From Max Holtzberg (2013-9-30).
* tools/define.sh: 'cut' long because as it once did. Script * tools/define.sh: 'cut' long because as it once did. Script
+205 -84
View File
@@ -57,6 +57,7 @@
#include "chip.h" #include "chip.h"
#include "chip/sam_adc.h" #include "chip/sam_adc.h"
#include "sam_dmac.h"
#include "sam_adc.h" #include "sam_adc.h"
#if defined(CONFIG_SAMA5_ADC) #if defined(CONFIG_SAMA5_ADC)
@@ -123,6 +124,19 @@
SAMA5_CHAN6_ENABLE || SAMA5_CHAN7_ENABLE || SAMA5_CHAN8_ENABLE || \ SAMA5_CHAN6_ENABLE || SAMA5_CHAN7_ENABLE || SAMA5_CHAN8_ENABLE || \
SAMA5_CHAN9_ENABLE || SAMA5_CHAN10_ENABLE || SAMA5_CHAN11_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 * Private Types
****************************************************************************/ ****************************************************************************/
@@ -133,6 +147,10 @@ struct sam_adc_s
{ {
#ifdef SAMA5_ADC_HAVE_CHANNELS #ifdef SAMA5_ADC_HAVE_CHANNELS
struct adc_dev_s dev; /* The external via of the ADC device */ 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 #endif
/* Debug stuff */ /* Debug stuff */
@@ -155,6 +173,14 @@ static bool sam_adc_checkreg(struct sam_adc_s *priv, bool wr,
uint32_t regval, uintptr_t address); uint32_t regval, uintptr_t address);
#endif #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 */ /* ADC interrupt handling */
#ifdef SAMA5_ADC_HAVE_CHANNELS #ifdef SAMA5_ADC_HAVE_CHANNELS
@@ -207,6 +233,9 @@ static struct adc_dev_s g_adcdev =
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Register Operations
****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: sam_adc_checkreg * Name: sam_adc_checkreg
* *
@@ -263,6 +292,169 @@ static bool sam_adc_checkreg(struct sam_adc_s *priv, bool wr,
#ifdef SAMA5_ADC_HAVE_CHANNELS #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 * Name: sam_adc_reset
* *
@@ -278,6 +470,12 @@ static void sam_adc_reset(struct adc_dev_s *dev)
irqstate_t flags; irqstate_t flags;
uint32_t regval; uint32_t regval;
#ifdef CONFIG_SAMA5_ADC_DMA
/* Stop any ongoing DMA */
sam_dmastop(priv->dma);
#endif
/* Reset the ADC controller */ /* Reset the ADC controller */
flags = irqsave(); flags = irqsave();
@@ -388,90 +586,6 @@ static int sam_adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg)
return -ENOTTY; 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
*
* 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 * Public Functions
****************************************************************************/ ****************************************************************************/
@@ -535,6 +649,13 @@ struct adc_dev_s *sam_adc_initialize(void)
sam_configpio(PIO_ADC_TRG); sam_configpio(PIO_ADC_TRG);
#endif #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 */ /* Reset the ADC controller */
sam_adc_putreg(priv, SAM_ADC_CR, ADC_CR_SWRST); sam_adc_putreg(priv, SAM_ADC_CR, ADC_CR_SWRST);
+182 -108
View File
@@ -67,12 +67,12 @@
* defined here so that it will be used consistently in all places. * defined here so that it will be used consistently in all places.
*/ */
#define DEV_FORMAT "/dev/input%d" #define DEV_FORMAT "/dev/input%d"
#define DEV_NAMELEN 16 #define DEV_NAMELEN 16
/* Poll the pen position while the pen is down at this rate (50MS): */ /* 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 /* This is a value for the threshold that guantees a big difference on the
* first pendown (but can't overflow). * first pendown (but can't overflow).
@@ -80,13 +80,36 @@
#define INVALID_THRESHOLD 0x1000 #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 * Private Types
****************************************************************************/ ****************************************************************************/
/* This describes the state of one contact */ /* This describes the state of one contact */
enum sam_contact_3 enum sam_contact_e
{ {
CONTACT_NONE = 0, /* No contact */ CONTACT_NONE = 0, /* No contact */
CONTACT_DOWN, /* First contact */ CONTACT_DOWN, /* First contact */
@@ -107,13 +130,15 @@ struct sam_sample_s
/* This structure describes the state of one touchscreen driver instance */ /* 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 nwaiters; /* Number of threads waiting for touchscreen data */
uint8_t id; /* Current touch point ID */ uint8_t id; /* Current touch point ID */
uint8_t status; /* Data ready/pen status bit set */
volatile bool penchange; /* An unreported event is buffered */ volatile bool penchange; /* An unreported event is buffered */
uint16_t threshx; /* Thresholding X value */ uint16_t threshx; /* Thresholding X value */
uint16_t threshy; /* Thresholding Y 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 devsem; /* Manages exclusive access to this structure */
sem_t waitsem; /* Used to wait for the availability of data */ 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 */ /* Interrupt bottom half logic and data sampling */
static void sam_notify(FAR struct sam_dev_s *priv); static void sam_notify(struct sam_tsd_s *priv);
static int sam_sample(FAR struct sam_dev_s *priv, static int sam_sample(struct sam_tsd_s *priv, struct sam_sample_s *sample);
FAR struct sam_sample_s *sample); static int sam_waitsample(struct sam_tsd_s *priv,
static int sam_waitsample(FAR struct sam_dev_s *priv, struct sam_sample_s *sample);
FAR struct sam_sample_s *sample); static void sam_bottomhalf(void *arg);
static void sam_bottomhalf(FAR 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 */ /* Character driver methods */
static int sam_open(FAR struct file *filep); static int sam_open(struct file *filep);
static int sam_close(FAR struct file *filep); static int sam_close(struct file *filep);
static ssize_t sam_read(FAR struct file *filep, FAR char *buffer, static ssize_t sam_read(struct file *filep, char *buffer, size_t len);
size_t len); static int sam_ioctl(struct file *filep, int cmd, unsigned long arg);
static int sam_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
#ifndef CONFIG_DISABLE_POLL #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 #endif
/**************************************************************************** /****************************************************************************
@@ -177,7 +202,7 @@ static const struct file_operations g_tsdops =
/* The driver state structure is pre-allocated. */ /* The driver state structure is pre-allocated. */
static struct sam_dev_s g_tsd; static struct sam_tsd_s g_tsd;
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
@@ -187,7 +212,7 @@ static struct sam_dev_s g_tsd;
* Name: sam_notify * 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 #ifndef CONFIG_DISABLE_POLL
int i; int i;
@@ -230,8 +255,7 @@ static void sam_notify(FAR struct sam_dev_s *priv)
* Name: sam_sample * Name: sam_sample
****************************************************************************/ ****************************************************************************/
static int sam_sample(FAR struct sam_dev_s *priv, static int sam_sample(struct sam_tsd_s *priv, struct sam_sample_s *sample)
FAR struct sam_sample_s *sample)
{ {
irqstate_t flags; irqstate_t flags;
int ret = -EAGAIN; int ret = -EAGAIN;
@@ -284,8 +308,7 @@ static int sam_sample(FAR struct sam_dev_s *priv,
* Name: sam_waitsample * Name: sam_waitsample
****************************************************************************/ ****************************************************************************/
static int sam_waitsample(FAR struct sam_dev_s *priv, static int sam_waitsample(struct sam_tsd_s *priv, struct sam_sample_s *sample)
FAR struct sam_sample_s *sample)
{ {
irqstate_t flags; irqstate_t flags;
int ret; int ret;
@@ -361,58 +384,29 @@ errout:
return ret; return ret;
} }
/****************************************************************************
* 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 * 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 x;
uint16_t y; uint16_t y;
uint16_t xdiff; uint16_t xdiff;
@@ -428,6 +422,10 @@ static void sam_bottomhalf(FAR void *arg)
wd_cancel(priv->wdog); wd_cancel(priv->wdog);
/* Get the set of unmasked, pending ADC interrupts */
pending = priv->pending;
/* Get exclusive access to the driver data structure */ /* Get exclusive access to the driver data structure */
do do
@@ -556,18 +554,81 @@ static void sam_bottomhalf(FAR void *arg)
ignored: ignored:
/* Re-enable touchscreen interrupts. */ /* 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 */ /* Release our lock on the state structure */
sem_post(&priv->devsem); sem_post(&priv->devsem);
} }
/****************************************************************************
* 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 * Name: sam_open
****************************************************************************/ ****************************************************************************/
static int sam_open(FAR struct file *filep) static int sam_open(struct file *filep)
{ {
ivdbg("Opening\n"); ivdbg("Opening\n");
return OK; return OK;
@@ -577,7 +638,7 @@ static int sam_open(FAR struct file *filep)
* Name: sam_close * Name: sam_close
****************************************************************************/ ****************************************************************************/
static int sam_close(FAR struct file *filep) static int sam_close(struct file *filep)
{ {
ivdbg("Closing\n"); ivdbg("Closing\n");
return OK; return OK;
@@ -587,11 +648,11 @@ static int sam_close(FAR struct file *filep)
* Name: sam_read * 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; struct inode *inode;
FAR struct sam_dev_s *priv; struct sam_tsd_s *priv;
FAR struct touch_sample_s *report; struct touch_sample_s *report;
struct sam_sample_s sample; struct sam_sample_s sample;
int ret; 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; inode = filep->f_inode;
DEBUGASSERT(inode && inode->i_private); 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 /* Verify that the caller has provided a buffer large enough to receive
* the touch data. * 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. * to the caller.
*/ */
report = (FAR struct touch_sample_s *)buffer; report = (struct touch_sample_s *)buffer;
memset(report, 0, SIZEOF_TOUCH_SAMPLE_S(1)); memset(report, 0, SIZEOF_TOUCH_SAMPLE_S(1));
report->npoints = 1; report->npoints = 1;
report->point[0].id = sample.id; report->point[0].id = sample.id;
report->point[0].x = sample.x; report->point[0].x = sample.x;
report->point[0].y = sample.y; report->point[0].y = sample.y;
/* Report the appropriate flags */ /* Report the appropriate flags */
@@ -716,18 +777,18 @@ errout:
* Name:sam_ioctl * 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; struct inode *inode;
FAR struct sam_dev_s *priv; struct sam_tsd_s *priv;
int ret; int ret;
ivdbg("cmd: %d arg: %ld\n", cmd, arg); ivdbg("cmd: %d arg: %ld\n", cmd, arg);
DEBUGASSERT(filep); DEBUGASSERT(filep);
inode = filep->f_inode; inode = filep->f_inode;
DEBUGASSERT(inode && inode->i_private); 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 */ /* 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 #ifndef CONFIG_DISABLE_POLL
static int sam_poll(FAR struct file *filep, FAR struct pollfd *fds, static int sam_poll(struct file *filep, struct pollfd *fds, bool setup)
bool setup)
{ {
FAR struct inode *inode; struct inode *inode;
FAR struct sam_dev_s *priv; struct sam_tsd_s *priv;
int ret = OK; int ret = OK;
int i; int i;
ivdbg("setup: %d\n", (int)setup); ivdbg("setup: %d\n", (int)setup);
DEBUGASSERT(filep && fds); DEBUGASSERT(filep && fds);
inode = filep->f_inode; inode = filep->f_inode;
DEBUGASSERT(inode && inode->i_private); 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? */ /* 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) 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]; char devname[DEV_NAMELEN];
int ret; int ret;
@@ -883,7 +943,7 @@ int sam_tsd_register(struct adc_dev_s *dev, int minor)
/* Initialize the touchscreen device driver instance */ /* 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->dev = dev; /* Save the ADC device handle */
priv->wdog = wd_create(); /* Create a watchdog timer */ priv->wdog = wd_create(); /* Create a watchdog timer */
priv->threshx = INVALID_THRESHOLD; /* Initialize thresholding logic */ priv->threshx = INVALID_THRESHOLD; /* Initialize thresholding logic */
@@ -941,29 +1001,43 @@ errout_with_priv:
* Handles ADC interrupts associated with touchscreen channels * Handles ADC interrupts associated with touchscreen channels
* *
* Input parmeters: * Input parmeters:
* None * pending - Current set of pending interrupts being handled
* *
* Returned Value: * Returned Value:
* None * 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; int ret;
/* Disable further touchscreen interrupts */ /* Are there pending TSD interrupts? */
sam_adc_putreg32(priv->dev, SAM_ADC_IDR, ADC_TSD_INTS); if ((pending & ADC_TSD_ALLINTS) != 0)
/* Schedule sampling to occur on the worker thread */
ret = sam_schedule(priv);
if (ret < 0)
{ {
idbg("ERROR: sam_schedule failed: %d\n", ret); /* Disable further touchscreen interrupts */
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 & 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; return ret;
} }