Add a timeout to the STMPE11 touchscreen driver to catch missing pen up events
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4758 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
7b3d644c0a
commit
4b1d8c0f2a
@ -2796,5 +2796,7 @@
|
|||||||
keyboard data in multi-user mode.
|
keyboard data in multi-user mode.
|
||||||
* graphics/nxconsole/nxcon_kdbind.c: Fixed unmatched sem_wait and sem_post.
|
* graphics/nxconsole/nxcon_kdbind.c: Fixed unmatched sem_wait and sem_post.
|
||||||
Fix some conditional compilation that included a few too many lines of code.
|
Fix some conditional compilation that included a few too many lines of code.
|
||||||
|
* drivers/input/stmpe11_tsc.c and stmpe11.h: Add a timeout to catch missed
|
||||||
|
pen up events. Now the STM3240G-EVAL touchscreen works very smoothly.
|
||||||
|
|
||||||
|
|
||||||
|
18
TODO
18
TODO
@ -17,7 +17,7 @@ nuttx/
|
|||||||
(3) USB (drivers/usbdev, drivers/usbhost)
|
(3) USB (drivers/usbdev, drivers/usbhost)
|
||||||
(8) Libraries (lib/)
|
(8) Libraries (lib/)
|
||||||
(10) File system/Generic drivers (fs/, drivers/)
|
(10) File system/Generic drivers (fs/, drivers/)
|
||||||
(4) Graphics subystem (graphics/)
|
(5) Graphics subystem (graphics/)
|
||||||
(1) Pascal add-on (pcode/)
|
(1) Pascal add-on (pcode/)
|
||||||
(1) Documentation (Documentation/)
|
(1) Documentation (Documentation/)
|
||||||
(7) Build system / Toolchains
|
(7) Build system / Toolchains
|
||||||
@ -757,6 +757,8 @@ o File system / Generic drivers (fs/, drivers/)
|
|||||||
o Graphics subystem (graphics/)
|
o Graphics subystem (graphics/)
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
See also the NxWidgets TODO list file for related issues.
|
||||||
|
|
||||||
Title: UNTESTED GRAPHICS APIS
|
Title: UNTESTED GRAPHICS APIS
|
||||||
Description: Testing of all APIs is not complete. See
|
Description: Testing of all APIs is not complete. See
|
||||||
http://nuttx.sourceforge.net/NXGraphicsSubsystem.html#testcoverage
|
http://nuttx.sourceforge.net/NXGraphicsSubsystem.html#testcoverage
|
||||||
@ -781,7 +783,7 @@ o Graphics subystem (graphics/)
|
|||||||
Priority: Low
|
Priority: Low
|
||||||
|
|
||||||
Title: AUTO-RAISE DISABLED
|
Title: AUTO-RAISE DISABLED
|
||||||
Descption: Auto-raise is currently disabled in NX multi-server mode. The
|
Description: Auto-raise is currently disabled in NX multi-server mode. The
|
||||||
reason is complex:
|
reason is complex:
|
||||||
- Most touchscreen controls send touch data a high rates
|
- Most touchscreen controls send touch data a high rates
|
||||||
- In multi-server mode, touch events get queued in a message
|
- In multi-server mode, touch events get queued in a message
|
||||||
@ -795,6 +797,18 @@ o Graphics subystem (graphics/)
|
|||||||
Status: Open
|
Status: Open
|
||||||
Priority: Medium low
|
Priority: Medium low
|
||||||
|
|
||||||
|
Title: IMPROVED NXCONSOLE FONT CACHING
|
||||||
|
Description: Now each NxConsole instance has its own private font cache
|
||||||
|
whose size is determined by CONFIG_NXCONSOLE_MXCHARS. If there
|
||||||
|
are multiple NxConsole instances using the same font, each will
|
||||||
|
have a separate font cache. This is inefficient and wasteful
|
||||||
|
of memory: Each NxConsole instance should share a common font
|
||||||
|
cache.
|
||||||
|
Status: Open
|
||||||
|
Priority: Medium. Not important for day-to-day testing but would be
|
||||||
|
a critical improvement if NxConsole were to be used in a
|
||||||
|
product.
|
||||||
|
|
||||||
o Pascal Add-On (pcode/)
|
o Pascal Add-On (pcode/)
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -46,8 +46,10 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <wdog.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
#include <nuttx/clock.h>
|
||||||
#include <nuttx/wqueue.h>
|
#include <nuttx/wqueue.h>
|
||||||
#include <nuttx/input/stmpe11.h>
|
#include <nuttx/input/stmpe11.h>
|
||||||
|
|
||||||
@ -92,6 +94,10 @@
|
|||||||
#define STMPE11_FLAGS_ADC_INITIALIZED (1 << 2) /* 1: The ADC block has been initialized */
|
#define STMPE11_FLAGS_ADC_INITIALIZED (1 << 2) /* 1: The ADC block has been initialized */
|
||||||
#define STMPE11_FLAGS_TS_INITIALIZED (1 << 3) /* 1: The TS block has been initialized */
|
#define STMPE11_FLAGS_TS_INITIALIZED (1 << 3) /* 1: The TS block has been initialized */
|
||||||
|
|
||||||
|
/* Timeout to detect missing pen up events */
|
||||||
|
|
||||||
|
#define STMPE11_PENUP_TICKS ((100 + (MSEC_PER_TICK-1)) / MSEC_PER_TICK)
|
||||||
|
|
||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
@ -137,6 +143,7 @@ struct stmpe11_dev_s
|
|||||||
|
|
||||||
uint8_t inuse; /* SMTPE11 pins in use */
|
uint8_t inuse; /* SMTPE11 pins in use */
|
||||||
uint8_t flags; /* See SMTPE11_FLAGS_* definitions */
|
uint8_t flags; /* See SMTPE11_FLAGS_* definitions */
|
||||||
|
struct work_s work; /* Supports the interrupt handling "bottom half" */
|
||||||
|
|
||||||
/* Fields that may be disabled to save size if touchscreen support is not used. */
|
/* Fields that may be disabled to save size if touchscreen support is not used. */
|
||||||
|
|
||||||
@ -153,7 +160,8 @@ struct stmpe11_dev_s
|
|||||||
uint16_t threshy; /* Thresholded Y value */
|
uint16_t threshy; /* Thresholded Y value */
|
||||||
sem_t waitsem; /* Used to wait for the availability of data */
|
sem_t waitsem; /* Used to wait for the availability of data */
|
||||||
|
|
||||||
struct work_s work; /* Supports the interrupt handling "bottom half" */
|
struct work_s timeout; /* Supports tiemeout work */
|
||||||
|
WDOG_ID wdog; /* Timeout to detect missing pen down events */
|
||||||
struct stmpe11_sample_s sample; /* Last sampled touch point data */
|
struct stmpe11_sample_s sample; /* Last sampled touch point data */
|
||||||
|
|
||||||
/* The following is a list if poll structures of threads waiting for
|
/* The following is a list if poll structures of threads waiting for
|
||||||
|
@ -183,16 +183,23 @@ static int stmpe11_interrupt(int irq, FAR void *context)
|
|||||||
|
|
||||||
config->enable(config, false);
|
config->enable(config, false);
|
||||||
|
|
||||||
/* Transfer processing to the worker thread. Since STMPE11 interrupts are
|
/* Check if interrupt work is already queue. If it is already busy, then
|
||||||
* disabled while the work is pending, no special action should be required
|
* we already have interrupt processing in the pipeline and we need to do
|
||||||
* to protected the work queue.
|
* nothing more.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(work_available(&priv->work));
|
if (work_available(&priv->work))
|
||||||
ret = work_queue(&priv->work, stmpe11_worker, priv, 0);
|
|
||||||
if (ret != 0)
|
|
||||||
{
|
{
|
||||||
illdbg("Failed to queue work: %d\n", ret);
|
/* Yes.. Transfer processing to the worker thread. Since STMPE11
|
||||||
|
* interrupts are disabled while the work is pending, no special
|
||||||
|
* action should be required to protect the work queue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = work_queue(&priv->work, stmpe11_worker, priv, 0);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
illdbg("Failed to queue work: %d\n", ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear any pending interrupts and return success */
|
/* Clear any pending interrupts and return success */
|
||||||
|
@ -315,7 +315,7 @@ static inline int stmpe11_waitsample(FAR struct stmpe11_dev_s *priv,
|
|||||||
* the failure now.
|
* the failure now.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
idbg("sem_wait failed: %d\n", errval);
|
idbg("ERROR: sem_wait failed: %d\n", errval);
|
||||||
DEBUGASSERT(errval == EINTR);
|
DEBUGASSERT(errval == EINTR);
|
||||||
#endif
|
#endif
|
||||||
ret = -EINTR;
|
ret = -EINTR;
|
||||||
@ -677,7 +677,7 @@ static int stmpe11_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
|||||||
|
|
||||||
if ((fds->events & POLLIN) == 0)
|
if ((fds->events & POLLIN) == 0)
|
||||||
{
|
{
|
||||||
idbg("Missing POLLIN: revents: %08x\n", fds->revents);
|
idbg("ERROR: Missing POLLIN: revents: %08x\n", fds->revents);
|
||||||
ret = -EDEADLK;
|
ret = -EDEADLK;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
@ -702,7 +702,7 @@ static int stmpe11_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
|||||||
|
|
||||||
if (i >= CONFIG_STMPE11_NPOLLWAITERS)
|
if (i >= CONFIG_STMPE11_NPOLLWAITERS)
|
||||||
{
|
{
|
||||||
idbg("No availabled slot found: %d\n", i);
|
idbg("ERROR: No availabled slot found: %d\n", i);
|
||||||
fds->priv = NULL;
|
fds->priv = NULL;
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
goto errout;
|
goto errout;
|
||||||
@ -734,6 +734,64 @@ errout:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stmpe11_timeoutworker
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* A timer has expired without receiving a pen up event. Check again.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void stmpe11_timeoutworker(FAR void *arg)
|
||||||
|
{
|
||||||
|
FAR struct stmpe11_dev_s *priv = (FAR struct stmpe11_dev_s *)arg;
|
||||||
|
|
||||||
|
DEBUGASSERT(priv);
|
||||||
|
|
||||||
|
/* Treat the timeout just like an interrupt occurred */
|
||||||
|
|
||||||
|
stmpe11_tscworker(priv, stmpe11_getreg8(priv, STMPE11_INT_STA));
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stmpe11_timeout
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* A timer has expired without receiving a pen up event. Schedule work
|
||||||
|
* to check again.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void stmpe11_timeout(int argc, uint32_t arg1, ...)
|
||||||
|
{
|
||||||
|
FAR struct stmpe11_dev_s *priv = (FAR struct stmpe11_dev_s *)((uintptr_t)arg1);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Are we still stuck in the pen down state? */
|
||||||
|
|
||||||
|
if (priv->sample.contact == CONTACT_MOVE ||
|
||||||
|
priv->sample.contact == CONTACT_MOVE)
|
||||||
|
{
|
||||||
|
/* Yes... is the worker thread available? If not, then apparently
|
||||||
|
* we have work already pending?
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (work_available(&priv->timeout))
|
||||||
|
{
|
||||||
|
/* Yes.. Transfer processing to the worker thread. Since STMPE11
|
||||||
|
* interrupts are disabled while the work is pending, no special
|
||||||
|
* action should be required to protect the work queue.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = work_queue(&priv->timeout, stmpe11_timeoutworker, priv, 0);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
illdbg("Failed to queue work: %d\n", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stmpe11_tscinitialize
|
* Name: stmpe11_tscinitialize
|
||||||
*
|
*
|
||||||
@ -849,7 +907,7 @@ int stmpe11_register(STMPE11_HANDLE handle, int minor)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
int errval = errno;
|
int errval = errno;
|
||||||
idbg("sem_wait failed: %d\n", errval);
|
idbg("ERROR: sem_wait failed: %d\n", errval);
|
||||||
return -errval;
|
return -errval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -857,25 +915,35 @@ int stmpe11_register(STMPE11_HANDLE handle, int minor)
|
|||||||
|
|
||||||
if ((priv->inuse & TSC_PIN_SET) != 0)
|
if ((priv->inuse & TSC_PIN_SET) != 0)
|
||||||
{
|
{
|
||||||
idbg("TSC pins is already in-use: %02x\n", priv->inuse);
|
idbg("ERROR: TSC pins is already in-use: %02x\n", priv->inuse);
|
||||||
sem_post(&priv->exclsem);
|
sem_post(&priv->exclsem);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the TS structure to their default values */
|
/* Initialize the TS structure fields to their default values */
|
||||||
|
|
||||||
priv->minor = minor;
|
priv->minor = minor;
|
||||||
priv->penchange = false;
|
priv->penchange = false;
|
||||||
priv->threshx = 0;
|
priv->threshx = 0;
|
||||||
priv->threshy = 0;
|
priv->threshy = 0;
|
||||||
|
|
||||||
|
/* Create a timer for catching missed pen up conditions */
|
||||||
|
|
||||||
|
priv->wdog = wd_create();
|
||||||
|
if (!priv->wdog)
|
||||||
|
{
|
||||||
|
idbg("ERROR: Failed to create a watchdog\n", errno);
|
||||||
|
sem_post(&priv->exclsem);
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
/* Register the character driver */
|
/* Register the character driver */
|
||||||
|
|
||||||
snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor);
|
snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor);
|
||||||
ret = register_driver(devname, &g_stmpe11fops, 0666, priv);
|
ret = register_driver(devname, &g_stmpe11fops, 0666, priv);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
idbg("Failed to register driver %s: %d\n", devname, ret);
|
idbg("ERROR: Failed to register driver %s: %d\n", devname, ret);
|
||||||
sem_post(&priv->exclsem);
|
sem_post(&priv->exclsem);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -913,6 +981,10 @@ void stmpe11_tscworker(FAR struct stmpe11_dev_s *priv, uint8_t intsta)
|
|||||||
|
|
||||||
ASSERT(priv != NULL);
|
ASSERT(priv != NULL);
|
||||||
|
|
||||||
|
/* Cancel the missing pen up timer */
|
||||||
|
|
||||||
|
(void)wd_cancel(priv->wdog);
|
||||||
|
|
||||||
/* Get a pointer the callbacks for convenience (and so the code is not so
|
/* Get a pointer the callbacks for convenience (and so the code is not so
|
||||||
* ugly).
|
* ugly).
|
||||||
*/
|
*/
|
||||||
@ -1050,9 +1122,20 @@ void stmpe11_tscworker(FAR struct stmpe11_dev_s *priv, uint8_t intsta)
|
|||||||
|
|
||||||
stmpe11_notify(priv);
|
stmpe11_notify(priv);
|
||||||
|
|
||||||
/* Reset and clear all data in the FIFO */
|
/* If we think that the pend is still down, the start/re-start the pen up
|
||||||
|
* timer.
|
||||||
|
*/
|
||||||
|
|
||||||
ignored:
|
ignored:
|
||||||
|
if (priv->sample.contact == CONTACT_MOVE ||
|
||||||
|
priv->sample.contact == CONTACT_MOVE)
|
||||||
|
{
|
||||||
|
(void)wd_start(priv->wdog, STMPE11_PENUP_TICKS, stmpe11_timeout,
|
||||||
|
1, (uint32_t)((uintptr_t)priv));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset and clear all data in the FIFO */
|
||||||
|
|
||||||
stmpe11_putreg8(priv, STMPE11_FIFO_STA, FIFO_STA_FIFO_RESET);
|
stmpe11_putreg8(priv, STMPE11_FIFO_STA, FIFO_STA_FIFO_RESET);
|
||||||
stmpe11_putreg8(priv, STMPE11_FIFO_STA, 0);
|
stmpe11_putreg8(priv, STMPE11_FIFO_STA, 0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user