diff options
| author | Kumar Abhishek <abhishek.kakkar@hotmail.com> | 2012-08-16 15:14:16 +0530 | 
|---|---|---|
| committer | Kumar Abhishek <abhishek.kakkar@hotmail.com> | 2012-08-16 15:14:16 +0530 | 
| commit | a9beec902da2348e858dcd54550d99a40c1fbe87 (patch) | |
| tree | 81e88faebe2d6922aff034c650be02958e52c0a3 | |
| parent | 7334da9f7f7cd9ea03a80e9e85f62fe061455caf (diff) | |
| download | uGFX-a9beec902da2348e858dcd54550d99a40c1fbe87.tar.gz uGFX-a9beec902da2348e858dcd54550d99a40c1fbe87.tar.bz2 uGFX-a9beec902da2348e858dcd54550d99a40c1fbe87.zip | |
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
| -rw-r--r-- | drivers/touchpad/XPT2046/touchpad_lld.c | 155 | ||||
| -rw-r--r-- | include/touchpad_lld.h | 65 | 
2 files changed, 173 insertions, 47 deletions
| 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
 diff --git a/include/touchpad_lld.h b/include/touchpad_lld.h index 45a561d3..a3a7489c 100644 --- a/include/touchpad_lld.h +++ b/include/touchpad_lld.h @@ -49,41 +49,76 @@  	#define TOUCHPAD_HAS_PRESSURE	FALSE  #endif +#ifndef TOUCHPAD_SPI_PROLOGUE +    #define TOUCHPAD_SPI_PROLOGUE() +#endif + +#ifndef TOUCHPAD_SPI_EPILOGUE +    #define TOUCHPAD_SPI_EPILOGUE() +#endif +  /*===========================================================================*/  /* Driver types.                                                             */  /*===========================================================================*/ -typedef struct TOUCHPADDriver TOUCHPADDriver; +typedef struct _TOUCHPADDriver TOUCHPADDriver;  /**   * @brief	Structure representing a Touchpad driver.   */ -struct TOUCHPADDriver { -	/* -	 * @brief	Pointer to SPI driver. -	 */ -	SPIDriver *spid; - -	/* -	 * @brief	SPI configuration. -	 */ -	SPIConfig *spicfg;	 +struct _TOUCHPADDriver { +    /* +     * @brief   Pointer to SPI driver. +     * @note    SPI driver must be enabled in mcuconf.h and halconf.h +     */ +    SPIDriver       *spip; + +    /* +     * @brief   Pointer to the SPI configuration structure. +     * @note    The lowest possible speed ~ 1-2MHz is to be used, otherwise +     *          will result in a lot of noise +     */ +    const SPIConfig  *spicfg; + +    /* +     * @brief   Touchscreen controller TPIRQ pin GPIO port +     */ +    ioportid_t      tpIRQPort; + +    /* +     * @brief   Touchscreen controller TPIRQ GPIO pin +     * @note    The interface is polled as of now, interrupt support is +     *          to be implemented in the future. +     */ +    ioportmask_t    tpIRQPin; + +    /* +     * @brief   Initialize the SPI with the configuration struct given or not +     *          If TRUE, spiStart is called by the init, otherwise not +     * @note    This is provided in such a case when SPI port is being shared +     *          across multiple peripherals, so not to disturb the SPI bus. +     *          You can use TOUCHPAD_SPI_PROLOGUE() and TOUCHPAD_SPI_EPILOGUE() +     *          macros to change the SPI configuration or speed before and +     *          after using the touchpad. An example case would be sharing the +     *          bus with a fast flash memory chip. +     */ +    bool_t          direct_init;  }; +  /*===========================================================================*/  /* External declarations.                                                    */  /*===========================================================================*/ -#if !defined(__DOXYGEN__) -    extern TOUCHPADDriver Touchpad; -#endif  #ifdef __cplusplus  extern "C" {  #endif  	/* Core functions */ -	void tp_lld_init(TOUCHPADDriver *tp); +	void tp_lld_init(const TOUCHPADDriver *tp); + +	uint16_t tp_lld_read_value(uint8_t cmd);  	uint16_t tp_lld_read_x(void);  	uint16_t tp_lld_read_y(void); | 
