diff --git a/drivers/stmpe811/Makefile.include b/drivers/stmpe811/Makefile.include index 66e6da5c94..656f2ec0d8 100644 --- a/drivers/stmpe811/Makefile.include +++ b/drivers/stmpe811/Makefile.include @@ -3,3 +3,7 @@ USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_stmpe811) PSEUDOMODULES += stmpe811_i2c PSEUDOMODULES += stmpe811_spi + +ifneq (,$(filter touch_dev,$(USEMODULE))) + CFLAGS += '-DSTMPE811_FIFO_THRESHOLD_ENABLED=1' +endif diff --git a/drivers/stmpe811/stmpe811.c b/drivers/stmpe811/stmpe811.c index bc0911851c..549e12dc92 100644 --- a/drivers/stmpe811/stmpe811.c +++ b/drivers/stmpe811/stmpe811.c @@ -46,6 +46,23 @@ #define ADDR (dev->params.addr) #endif +#ifndef STMPE811_FIFO_THRESHOLD_ENABLED +#define STMPE811_FIFO_THRESHOLD_ENABLED (0) +#endif + +/* The driver only works reliably with FIFO threshold interrupts if the FIFO + * threshold is at least 2. The reason is that all interrupts are cleared when + * the status is checked in `stmpe811_read_touch_state` but the FIFO Threshold + * interrupt is asserted again immediately since the FIFO is not read so that + * a new interrupt is pending. On the other hand, the Touch Detected interrupt + * does not work reliably for the release event if only the Touch Detected + * interrupt in `stmpe811_read_touch_state` is cleared. The workaround is + * to set the FIFO threshold to at least 2 to introduce a small delay between + * the Touch Detect interrupt on a touch and the first FIFO threshold + * interrupt. */ +#ifndef STMPE811_FIFO_THRESHOLD +#define STMPE811_FIFO_THRESHOLD (STMPE811_FIFO_THRESHOLD_ENABLED ? 2 : 1) +#endif #if IS_USED(MODULE_STMPE811_SPI) /* using SPI mode */ static inline void _acquire(const stmpe811_t *dev) @@ -194,7 +211,7 @@ int stmpe811_init(stmpe811_t *dev, const stmpe811_params_t *params, stmpe811_eve } /* check mode configuration */ - if(_stmpe811_check_mode(dev) != 0) { + if (_stmpe811_check_mode(dev) != 0) { DEBUG("[stmpe811] error: couldn't setup SPI\n"); return -EIO; } @@ -257,7 +274,7 @@ int stmpe811_init(stmpe811_t *dev, const stmpe811_params_t *params, stmpe811_eve ret += _write_reg(dev, STMPE811_TSC_CFG, reg); /* set fifo threshold */ - ret += _write_reg(dev, STMPE811_FIFO_TH, 0x01); + ret += _write_reg(dev, STMPE811_FIFO_TH, STMPE811_FIFO_THRESHOLD); /* reset fifo */ _reset_fifo(dev); @@ -287,7 +304,9 @@ int stmpe811_init(stmpe811_t *dev, const stmpe811_params_t *params, stmpe811_eve } /* Enable touchscreen interrupt */ - ret += _write_reg(dev, STMPE811_INT_EN, STMPE811_INT_EN_TOUCH_DET); + ret += _write_reg(dev, STMPE811_INT_EN, + STMPE811_INT_EN_TOUCH_DET | + (STMPE811_FIFO_THRESHOLD_ENABLED ? STMPE811_INT_EN_FIFO_TH : 0)); /* Enable global interrupt */ ret += _write_reg(dev, STMPE811_INT_CTRL, @@ -341,6 +360,14 @@ int stmpe811_read_touch_position(stmpe811_t *dev, stmpe811_touch_position_t *pos } #endif + /* Reset the FIFO, otherwise new touch data will be processed with a delay + * if the rate of calling this function to read the FIFO is slower than + * the rate at which the FIFO is filled. The reason for this is that with + * each call of this function only the oldest touch data is read + * value by value from the FIFO. Gestures, for example, can't be + * implemented with such a behavior. */ + _reset_fifo(dev); + /* Release device bus */ _release(dev); diff --git a/makefiles/driver_with_touch_dev.mk b/makefiles/driver_with_touch_dev.mk index 2b6afdd8c1..cf394855ab 100644 --- a/makefiles/driver_with_touch_dev.mk +++ b/makefiles/driver_with_touch_dev.mk @@ -4,7 +4,7 @@ TOUCH_DEV_INTERFACE ?= $(MODULE)_touch_dev.c # by default include all .c files except _touch_dev.c SRC = $(filter-out $(TOUCH_DEV_INTERFACE),$(wildcard *.c)) -# only include _touch_dev.c if saul module is used +# only include _touch_dev.c if touch_dev module is used ifneq (,$(filter touch_dev,$(USEMODULE))) SRC += $(TOUCH_DEV_INTERFACE) endif