From a9beec902da2348e858dcd54550d99a40c1fbe87 Mon Sep 17 00:00:00 2001 From: Kumar Abhishek Date: Thu, 16 Aug 2012 15:14:16 +0530 Subject: XPT2046 LLD Major Update Added 7 point median filtering to reduce noise TOUCHPADDriver structure now encapsulates the IRQ pin, so removed the TP_CS_ and TP_IRQ_ macros Added generic tp_lld_read_value method to read any ADC channel from the XPT2046, this includes on-chip temperature sensor and VBAT input Improved SPI bus sharing, with the optional TOUCHPAD_SPI_PROLOGUE and TOUCHPAD_SPI_EPILOGUE macros --- drivers/touchpad/XPT2046/touchpad_lld.c | 155 +++++++++++++++++++++++++------- 1 file changed, 123 insertions(+), 32 deletions(-) (limited to 'drivers/touchpad') diff --git a/drivers/touchpad/XPT2046/touchpad_lld.c b/drivers/touchpad/XPT2046/touchpad_lld.c index 24afcab4..16e4db79 100644 --- a/drivers/touchpad/XPT2046/touchpad_lld.c +++ b/drivers/touchpad/XPT2046/touchpad_lld.c @@ -36,9 +36,6 @@ /* Driver local definitions. */ /*===========================================================================*/ -#define TP_CS_HIGH palSetPad(TP_CS_PORT, TP_CS) -#define TP_CS_LOW palClearPad(TP_CS_PORT, TP_CS) - #ifdef UNUSED #elif defined(__GNUC__) # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) @@ -52,13 +49,15 @@ /* Driver exported variables. */ /*===========================================================================*/ -#if !defined(__DOXYGEN__) - TOUCHPADDriver Touchpad; -#endif - /*===========================================================================*/ /* Driver local variables. */ /*===========================================================================*/ +#if !defined(__DOXYGEN__) + /* Local copy of the current touchpad driver */ + static const TOUCHPADDriver *tpDriver; + + static uint16_t sampleBuf[7]; +#endif /*===========================================================================*/ /* Driver local functions. */ @@ -79,30 +78,104 @@ * * @notapi */ -void tp_lld_init(TOUCHPADDriver *tp) { - spiStart(tp->spid, tp->spicfg); +void tp_lld_init(const TOUCHPADDriver *tp) { + tpDriver=tp; + + if (tpDriver->direct_init) + spiStart(tpDriver->spip, tpDriver->spicfg); +} + + +/** + * @brief Reads a conversion from the touchpad + * + * @param[in] cmd The command bits to send to the touchpad + * + * @return The read value 12-bit right-justified + * + * @note This function only reads data, it is assumed that the pins are + * configured properly and the bus has been acquired beforehand + * + * @notapi + */ +uint16_t tp_lld_read_value(uint8_t cmd) { + static uint8_t txbuf[3]={0}; + static uint8_t rxbuf[3]={0}; + uint16_t ret; + + txbuf[0]=cmd; + + spiExchange(tpDriver->spip, 3, txbuf, rxbuf); + + ret = (rxbuf[1] << 5) | (rxbuf[2] >> 3); + + return ret; +} + +/** + * @brief 7-point median filtering code for touchpad samples + * + * @note This is an internally used routine only. + * + * @notapi + */ +static void tp_lld_filter(void) { + uint16_t temp; + int i,j; + + for (i=0; i<4; i++) { + for (j=i; j<7; j++) { + if (sampleBuf[i] > sampleBuf[j]) { + /* Swap the values */ + temp=sampleBuf[i]; + sampleBuf[i]=sampleBuf[j]; + sampleBuf[j]=temp; + } + } + } + } /** * @brief Reads out the X direction. * + * @note The samples are median filtered for greater noise reduction + * * @notapi */ uint16_t tp_lld_read_x(void) { - uint8_t txbuf[1]; - uint8_t rxbuf[2]; - uint16_t x; + int i; + +#if defined(SPI_USE_MUTUAL_EXCLUSION) + spiAcquireBus(tpDriver->spip); +#endif + + TOUCHPAD_SPI_PROLOGUE(); + palClearPad(tpDriver->spicfg->ssport, tpDriver->spicfg->sspad); + + /* Discard the first conversion - very noisy and keep the ADC on hereafter + * till we are done with the sampling. Note that PENIRQ is disabled. + */ + tp_lld_read_value(0xD1); + + for (i=0;i<7;i++) { + sampleBuf[i]=tp_lld_read_value(0xD1); + } - txbuf[0] = 0xd0; - TP_CS_LOW; - spiSend(&SPID1, 1, txbuf); - spiReceive(&SPID1, 2, rxbuf); - TP_CS_HIGH; + /* Switch on PENIRQ once again - perform a dummy read */ + tp_lld_read_value(0xD0); - x = rxbuf[0] << 4; - x |= rxbuf[1] >> 4; + palSetPad(tpDriver->spicfg->ssport, tpDriver->spicfg->sspad); + TOUCHPAD_SPI_EPILOGUE(); - return x; +#if defined(SPI_USE_MUTUAL_EXCLUSION) + spiReleaseBus(tpDriver->spip); +#endif + + /* Find the median - use selection sort */ + tp_lld_filter(); + + return sampleBuf[3]; } /* @@ -111,20 +184,38 @@ uint16_t tp_lld_read_x(void) { * @notapi */ uint16_t tp_lld_read_y(void) { - uint8_t txbuf[1]; - uint8_t rxbuf[2]; - uint16_t y; + int i; + +#if defined(SPI_USE_MUTUAL_EXCLUSION) + spiAcquireBus(tpDriver->spip); +#endif + + TOUCHPAD_SPI_PROLOGUE(); + palClearPad(tpDriver->spicfg->ssport, tpDriver->spicfg->sspad); - txbuf[0] = 0x90; - TP_CS_LOW; - spiSend(&SPID1, 1, txbuf); - spiReceive(&SPID1, 2, rxbuf); - TP_CS_HIGH; + /* Discard the first conversion - very noisy and keep the ADC on hereafter + * till we are done with the sampling. Note that PENIRQ is disabled. + */ + tp_lld_read_value(0x91); + + for (i=0;i<7;i++) { + sampleBuf[i]=tp_lld_read_value(0x91); + } + + /* Switch on PENIRQ once again - perform a dummy read */ + tp_lld_read_value(0x90); + + palSetPad(tpDriver->spicfg->ssport, tpDriver->spicfg->sspad); + TOUCHPAD_SPI_EPILOGUE(); + +#ifdef SPI_USE_MUTUAL_EXCLUSION + spiReleaseBus(tpDriver->spip); +#endif - y = rxbuf[0] << 4; - y |= rxbuf[1] >> 4; + /* Find the median - use selection sort */ + tp_lld_filter(); - return y; + return sampleBuf[3]; } /* ---- Optional Routines ---- */ @@ -137,7 +228,7 @@ uint16_t tp_lld_read_y(void) { * @notapi */ uint8_t tp_lld_irq(void) { - return (!palReadPad(TP_IRQ_PORT, TP_IRQ)); + return (!palReadPad(tpDriver->tpIRQPort, tpDriver->tpIRQPin)); } #endif -- cgit v1.2.3