diff --git a/configs/lpcxpresso-lpc54628/README.txt b/configs/lpcxpresso-lpc54628/README.txt index f88a7553ada4648a6660db801fed2eb6a57fb89c..a9a91f3c4ea6c18532bd4a8f088ac5e7094bb4e8 100644 --- a/configs/lpcxpresso-lpc54628/README.txt +++ b/configs/lpcxpresso-lpc54628/README.txt @@ -67,10 +67,7 @@ STATUS 2017-12-18: Added an option to the FT5x06 driver to support a timer- based poll instead of interrupts. This is very inefficient in that it will introduce delays in touchscreen response and will consume more CPU - bandwidth. - - The FT5x06 driver is not, however, functional. It is generating hard - faults. + bandwidth. The driver appears to be functional. Configurations ============== @@ -178,8 +175,23 @@ Configurations Touch panel I2C address: 0x38 4. The touchscreen test program at apps/examples/touchscreen is also - included in this configuration. As of this writing, touchscreen - is not yet functional, however. + included in this configuration. + + nsh> tc 5 + tc_main: nsamples: 2 + tc_main: Initializing external touchscreen device + tc_main: Opening /dev/input0 + Sample : + npoints : 1 + Point 1 : + id : 0 + flags : 1a + x : 230 + y : 84 + h : 0 + w : 0 + pressure : 0 + etc. nsh: diff --git a/configs/lpcxpresso-lpc54628/fb/defconfig b/configs/lpcxpresso-lpc54628/fb/defconfig index a6e853d527e2a493f21ae74571a6dae1cf36e1dd..f24fb6216beaa643d8d09649113df2138eee88ed 100644 --- a/configs/lpcxpresso-lpc54628/fb/defconfig +++ b/configs/lpcxpresso-lpc54628/fb/defconfig @@ -18,6 +18,7 @@ CONFIG_FAT_LFN=y CONFIG_FS_FAT=y CONFIG_FS_PROCFS=y CONFIG_FT5X06_POLLMODE=y +CONFIG_FT5X06_SINGLEPOINT=y CONFIG_GRAPHICS_PDCURSES=y CONFIG_I2CTOOL_MAXBUS=9 CONFIG_INPUT_FT5X06=y diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 477f66830a61e96686271e51f7612d3b65713160..a190c49428ce321dd0b1e83ac56ce02f104fe225 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -78,7 +78,7 @@ config INPUT_FT5336 if INPUT_FT5X06 config FT5X06_POLLMODE - bool " FT5336/FT5x06 polled mode" + bool "Polled mode" default n ---help--- Run the FT5x06 in a non-interrupt driven polled mode. Events will @@ -88,6 +88,40 @@ config FT5X06_POLLMODE in detecting touch related events and (2) it will consume a significant amount of CPU time to perform the polling. +config FT5X06_SWAPXY + bool "Swap X/Y" + default n + ---help--- + Reverse the meaning of X and Y to handle different LCD orientations. + +config FT5X06_SINGLEPOINT + bool "Single point" + default n + ---help--- + Do no report multi-touch events + +if FT5X06_SINGLEPOINT + +config FT5X06_THRESHX + int "X threshold" + default 12 + ---help--- + New touch positions will only be reported when the X or Y data changes by these + thresholds. This trades reduced data rates for some loss in dragging accuracy. For + 12-bit values the raw ranges are 0-4095. So for example, if your display is + 320x240, then THRESHX=13 and THRESHY=17 would correspond to one pixel. Default: 12 + +config FT5X06_THRESHY + int "Y threshold" + default 12 + ---help--- + New touch positions will only be reported when the X or Y data changes by these + thresholds. This trades reduced data rates for some loss in dragging accuracy. For + 12-bit values the raw ranges are 0-4095. So for example, if your display is + 320x240, then THRESHX=13 and THRESHY=17 would correspond to one pixel. Default: 12 + +endif # FT5X06_SINGLEPOINT + config FT5X06_NPOLLWAITERS int "Number FT5336/FT5x06 poll waiters" default 4 diff --git a/drivers/input/ft5x06.c b/drivers/input/ft5x06.c index ed7e4b9224d5734f1b8b55dbf71991cec13d9608..9ce827e1efd60ebec34e3dc68b09add65a6492dc 100644 --- a/drivers/input/ft5x06.c +++ b/drivers/input/ft5x06.c @@ -120,6 +120,12 @@ struct ft5x06_dev_s * FT5x06 data */ volatile bool valid; /* True: New, valid touch data in * touchbuf[] */ +#ifdef CONFIG_FT5X06_SINGLEPOINT + uint8_t lastid; /* Last reported touch id */ + uint8_t lastevent; /* Last reported event */ + int16_t lastx; /* Last reported X position */ + int16_t lasty; /* Last reported Y position */ +#endif sem_t devsem; /* Manages exclusive access to this * structure */ sem_t waitsem; /* Used to wait for the @@ -299,7 +305,12 @@ static void ft5x06_data_worker(FAR void *arg) msg[0].buffer = ®addr; /* Send one byte of data (no STOP) */ msg[0].length = 1; - /* Set up the data read operation */ + /* Set up the data read operation. + * + * REVISIT: If CONFIG_FT5X06_SINGLEPOINT is selected, we we not just + * set the length for one sample? Or is there some reason why we have to + * read all of the points? + */ msg[1].frequency = priv->frequency; /* I2C frequency */ msg[1].addr = config->address; /* 7-bit address */ @@ -427,6 +438,113 @@ static int ft5x06_data_interrupt(int irq, FAR void *context, FAR void *arg) * Name: ft5x06_sample ****************************************************************************/ +#ifdef CONFIG_FT5X06_SINGLEPOINT +static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer, + size_t len) +{ + FAR struct ft5x06_touch_data_s *raw; + FAR struct ft5x06_touch_point_s *touch; + FAR struct touch_sample_s *sample; + FAR struct touch_point_s *point; + int16_t x; + int16_t y; + uint8_t event; + uint8_t id; + + if (!priv->valid) + { + return 0; /* Nothing to read */ + } + + /* Raw data pointers (source) */ + + raw = (FAR struct ft5x06_touch_data_s *)priv->touchbuf; + + if (raw->tdstatus != 1) + { + priv->valid = false; + return 0; /* No touches read. */ + } + + /* Get the reported X and Y positions */ + + touch = raw->touch; + + #ifdef CONFIG_FT5X06_SWAPXY + y = TOUCH_POINT_GET_X(touch[0]); + x = TOUCH_POINT_GET_Y(touch[0]); +#else + x = TOUCH_POINT_GET_X(touch[0]); + y = TOUCH_POINT_GET_Y(touch[0]); +#endif + + /* Get the touch point ID and event */ + + event = TOUCH_POINT_GET_EVENT(touch[0]); + id = TOUCH_POINT_GET_ID(touch[0]); + + if (id == priv->lastid && event == priv->lastevent) + { + int16_t deltax; + int16_t deltay; + + /* Same ID and event.. Compare the change in position from the last + * report. + */ + + deltax = (x - priv->lastx); + if (deltax < 0) + { + deltax = -deltax; + } + + if (deltax < CONFIG_FT5X06_THRESHX) + { + /* There as been no significant change in X, try Y */ + + deltay = (y - priv->lasty); + if (deltay < 0) + { + deltay = -deltay; + } + + if (deltax < CONFIG_FT5X06_THRESHX) + { + /* Ignore... no significant change in Y either */ + + priv->valid = false; + return 0; /* No new touches read. */ + } + } + } + + priv->lastid = id; + priv->lastevent = event; + priv->lastx = x; + priv->lasty = y; + + /* User data buffer points (sink) */ + + /* Return the number of touches read */ + + sample = (FAR struct touch_sample_s *)buffer; + sample->npoints = 1; + + /* Decode and return the single touch point */ + + point = sample->point; + point[0].id = id; + point[0].flags = g_event_map[event]; + point[0].x = x; + point[0].y = y; + point[0].h = 0; + point[0].w = 0; + point[0].pressure = 0; + + priv->valid = false; + return SIZEOF_TOUCH_SAMPLE_S(1); +} +#else static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer, size_t len) { @@ -434,8 +552,8 @@ static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer, FAR struct ft5x06_touch_point_s *touch; FAR struct touch_sample_s *sample; FAR struct touch_point_s *point; - unsigned int ntouches; unsigned int maxtouches; + unsigned int ntouches; int i; maxtouches = (len - sizeof(int)) / sizeof(struct touch_point_s); @@ -454,6 +572,8 @@ static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer, /* Decode number of touches */ ntouches = raw->tdstatus; + DEBUGASSERT(ntouches <= FT5x06_MAX_TOUCHES); + if (ntouches > maxtouches) { ntouches = maxtouches; @@ -465,8 +585,6 @@ static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer, return 0; /* No touches read. */ } - DEBUGASSERT(ntouches <= FT5x06_MAX_TOUCHES); - /* User data buffer points (sink) */ sample = (FAR struct touch_sample_s *)buffer; @@ -478,14 +596,19 @@ static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer, /* Decode and return the touch points */ - for (i = 0; i < raw->tdstatus; i++) + for (i = 0; i < ntouches; i++) { int event = TOUCH_POINT_GET_EVENT(touch[i]); point[i].id = TOUCH_POINT_GET_ID(touch[i]); point[i].flags = g_event_map[event]; +#ifdef CONFIG_FT5X06_SWAPXY + point[i].y = TOUCH_POINT_GET_X(touch[i]); + point[i].x = TOUCH_POINT_GET_Y(touch[i]); +#else point[i].x = TOUCH_POINT_GET_X(touch[i]); point[i].y = TOUCH_POINT_GET_Y(touch[i]); +#endif point[i].h = 0; point[i].w = 0; point[i].pressure = 0; @@ -494,6 +617,7 @@ static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer, priv->valid = false; return SIZEOF_TOUCH_SAMPLE_S(ntouches); } +#endif /* CONFIG_FT5X06_SINGLEPOINT */ /**************************************************************************** * Name: ft5x06_waitsample