Merge pull request #43 from abhishek-kakkar/master

Touchpad Updates
ugfx_release_2.6
Tectu 2012-08-16 03:26:02 -07:00
commit df680e6d6e
5 changed files with 419 additions and 202 deletions

View File

@ -1,146 +1,237 @@
/* /*
ChibiOS-LCD-Driver - Copyright (C) 2012 ChibiOS-LCD-Driver - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org> Joel Bodenmann aka Tectu <joel@unormal.org>
This file is part of ChibiOS-LCD-Driver. This file is part of ChibiOS-LCD-Driver.
ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
ChibiOS-LCD-Driver is distributed in the hope that it will be useful, ChibiOS-LCD-Driver is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** /**
* @file touchpadADS7843/touchpad_lld.c * @file touchpadADS7843/touchpad_lld.c
* @brief Touchpad Driver subsystem low level driver source. * @brief Touchpad Driver subsystem low level driver source.
* *
* @addtogroup TOUCHPAD * @addtogroup TOUCHPAD
* @{ * @{
*/ */
#include "ch.h" #include "ch.h"
#include "hal.h" #include "hal.h"
#include "touchpad.h" #include "touchpad.h"
#if HAL_USE_TOUCHPAD || defined(__DOXYGEN__) #if HAL_USE_TOUCHPAD || defined(__DOXYGEN__)
/*===========================================================================*/ /*===========================================================================*/
/* Driver local definitions. */ /* Driver local definitions. */
/*===========================================================================*/ /*===========================================================================*/
#define TP_CS_HIGH palSetPad(TP_CS_PORT, TP_CS) #ifdef UNUSED
#define TP_CS_LOW palClearPad(TP_CS_PORT, TP_CS) #elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#ifdef UNUSED #elif defined(__LCLINT__)
#elif defined(__GNUC__) # define UNUSED(x) /*@unused@*/ x
# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) #else
#elif defined(__LCLINT__) # define UNUSED(x) x
# define UNUSED(x) /*@unused@*/ x #endif
#else
# define UNUSED(x) x /*===========================================================================*/
#endif /* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */ /*===========================================================================*/
/*===========================================================================*/ /* Driver local variables. */
/*===========================================================================*/
#if !defined(__DOXYGEN__) #if !defined(__DOXYGEN__)
TOUCHPADDriver Touchpad; /* Local copy of the current touchpad driver */
#endif static const TOUCHPADDriver *tpDriver;
/*===========================================================================*/ static uint16_t sampleBuf[7];
/* Driver local variables. */ #endif
/*===========================================================================*/
/*===========================================================================*/
/*===========================================================================*/ /* Driver local functions. */
/* Driver local functions. */ /*===========================================================================*/
/*===========================================================================*/
/*===========================================================================*/
/*===========================================================================*/ /* Driver interrupt handlers. */
/* Driver interrupt handlers. */ /*===========================================================================*/
/*===========================================================================*/
/*===========================================================================*/
/*===========================================================================*/ /* Driver exported functions. */
/* Driver exported functions. */ /*===========================================================================*/
/*===========================================================================*/
/* ---- Required Routines ---- */
/* ---- Required Routines ---- */
/**
/** * @brief Low level Touchpad driver initialization.
* @brief Low level Touchpad driver initialization. *
* * @notapi
* @notapi */
*/ void tp_lld_init(const TOUCHPADDriver *tp) {
void tp_lld_init(TOUCHPADDriver *tp) { tpDriver=tp;
spiStart(tp->spid, tp->spicfg);
} if (tpDriver->direct_init)
spiStart(tpDriver->spip, tpDriver->spicfg);
/** }
* @brief Reads out the X direction.
*
* @notapi /**
*/ * @brief Reads a conversion from the touchpad
uint16_t tp_lld_read_x(void) { *
uint8_t txbuf[1]; * @param[in] cmd The command bits to send to the touchpad
uint8_t rxbuf[2]; *
uint16_t x; * @return The read value 12-bit right-justified
*
txbuf[0] = 0xd0; * @note This function only reads data, it is assumed that the pins are
TP_CS_LOW; * configured properly and the bus has been acquired beforehand
spiSend(&SPID1, 1, txbuf); *
spiReceive(&SPID1, 2, rxbuf); * @notapi
TP_CS_HIGH; */
uint16_t tp_lld_read_value(uint8_t cmd) {
x = rxbuf[0] << 4; static uint8_t txbuf[3]={0};
x |= rxbuf[1] >> 4; static uint8_t rxbuf[3]={0};
uint16_t ret;
return x;
} txbuf[0]=cmd;
/* spiExchange(tpDriver->spip, 3, txbuf, rxbuf);
* @brief Reads out the Y direction.
* ret = (rxbuf[1] << 5) | (rxbuf[2] >> 3);
* @notapi
*/ return ret;
uint16_t tp_lld_read_y(void) { }
uint8_t txbuf[1];
uint8_t rxbuf[2]; /**
uint16_t y; * @brief 7-point median filtering code for touchpad samples
*
txbuf[0] = 0x90; * @note This is an internally used routine only.
TP_CS_LOW; *
spiSend(&SPID1, 1, txbuf); * @notapi
spiReceive(&SPID1, 2, rxbuf); */
TP_CS_HIGH; static void tp_lld_filter(void) {
uint16_t temp;
y = rxbuf[0] << 4; int i,j;
y |= rxbuf[1] >> 4;
for (i=0; i<4; i++) {
return y; for (j=i; j<7; j++) {
} if (sampleBuf[i] > sampleBuf[j]) {
/* Swap the values */
/* ---- Optional Routines ---- */ temp=sampleBuf[i];
#if TOUCHPAD_HAS_IRQ || defined(__DOXYGEN__) sampleBuf[i]=sampleBuf[j];
/* sampleBuf[j]=temp;
* @brief for checking if touchpad is pressed or not. }
* }
* @return 1 if pressed / 0 if not pressed }
*
* @noapi }
*/
uint8_t tp_lld_irq(void) { /**
return (!palReadPad(TP_IRQ_PORT, TP_IRQ)); * @brief Reads out the X direction.
} *
#endif * @note The samples are median filtered for greater noise reduction
*
#endif /* HAL_USE_TOUCHPAD */ * @notapi
/** @} */ */
uint16_t tp_lld_read_x(void) {
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);
}
/* Switch on PENIRQ once again - perform a dummy read */
tp_lld_read_value(0xD0);
palSetPad(tpDriver->spicfg->ssport, tpDriver->spicfg->sspad);
TOUCHPAD_SPI_EPILOGUE();
#if defined(SPI_USE_MUTUAL_EXCLUSION)
spiReleaseBus(tpDriver->spip);
#endif
/* Find the median - use selection sort */
tp_lld_filter();
return sampleBuf[3];
}
/*
* @brief Reads out the Y direction.
*
* @notapi
*/
uint16_t tp_lld_read_y(void) {
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(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
/* Find the median - use selection sort */
tp_lld_filter();
return sampleBuf[3];
}
/* ---- Optional Routines ---- */
#if TOUCHPAD_HAS_IRQ || defined(__DOXYGEN__)
/*
* @brief for checking if touchpad is pressed or not.
*
* @return 1 if pressed / 0 if not pressed
*
* @notapi
*/
uint8_t tp_lld_irq(void) {
return (!palReadPad(tpDriver->tpIRQPort, tpDriver->tpIRQPin));
}
#endif
#endif /* HAL_USE_TOUCHPAD */
/** @} */

View File

@ -36,9 +36,6 @@
/* Driver local definitions. */ /* 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 #ifdef UNUSED
#elif defined(__GNUC__) #elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
@ -52,13 +49,15 @@
/* Driver exported variables. */ /* Driver exported variables. */
/*===========================================================================*/ /*===========================================================================*/
#if !defined(__DOXYGEN__)
TOUCHPADDriver Touchpad;
#endif
/*===========================================================================*/ /*===========================================================================*/
/* Driver local variables. */ /* 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. */ /* Driver local functions. */
@ -79,30 +78,104 @@
* *
* @notapi * @notapi
*/ */
void tp_lld_init(TOUCHPADDriver *tp) { void tp_lld_init(const TOUCHPADDriver *tp) {
spiStart(tp->spid, tp->spicfg); 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. * @brief Reads out the X direction.
* *
* @note The samples are median filtered for greater noise reduction
*
* @notapi * @notapi
*/ */
uint16_t tp_lld_read_x(void) { uint16_t tp_lld_read_x(void) {
uint8_t txbuf[1]; int i;
uint8_t rxbuf[2];
uint16_t x;
txbuf[0] = 0xd0; #if defined(SPI_USE_MUTUAL_EXCLUSION)
TP_CS_LOW; spiAcquireBus(tpDriver->spip);
spiSend(&SPID1, 1, txbuf); #endif
spiReceive(&SPID1, 2, rxbuf);
TP_CS_HIGH;
x = rxbuf[0] << 4; TOUCHPAD_SPI_PROLOGUE();
x |= rxbuf[1] >> 4; palClearPad(tpDriver->spicfg->ssport, tpDriver->spicfg->sspad);
return x; /* 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);
}
/* Switch on PENIRQ once again - perform a dummy read */
tp_lld_read_value(0xD0);
palSetPad(tpDriver->spicfg->ssport, tpDriver->spicfg->sspad);
TOUCHPAD_SPI_EPILOGUE();
#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 * @notapi
*/ */
uint16_t tp_lld_read_y(void) { uint16_t tp_lld_read_y(void) {
uint8_t txbuf[1]; int i;
uint8_t rxbuf[2];
uint16_t y;
txbuf[0] = 0x90; #if defined(SPI_USE_MUTUAL_EXCLUSION)
TP_CS_LOW; spiAcquireBus(tpDriver->spip);
spiSend(&SPID1, 1, txbuf); #endif
spiReceive(&SPID1, 2, rxbuf);
TP_CS_HIGH;
y = rxbuf[0] << 4; TOUCHPAD_SPI_PROLOGUE();
y |= rxbuf[1] >> 4; palClearPad(tpDriver->spicfg->ssport, tpDriver->spicfg->sspad);
return y; /* 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
/* Find the median - use selection sort */
tp_lld_filter();
return sampleBuf[3];
} }
/* ---- Optional Routines ---- */ /* ---- Optional Routines ---- */
@ -137,7 +228,7 @@ uint16_t tp_lld_read_y(void) {
* @notapi * @notapi
*/ */
uint8_t tp_lld_irq(void) { uint8_t tp_lld_irq(void) {
return (!palReadPad(TP_IRQ_PORT, TP_IRQ)); return (!palReadPad(tpDriver->tpIRQPort, tpDriver->tpIRQPin));
} }
#endif #endif

View File

@ -70,7 +70,7 @@ struct cal {
extern "C" { extern "C" {
#endif #endif
void tpInit(TOUCHPADDriver *tp); void tpInit(const TOUCHPADDriver *tp);
uint16_t tpReadX(void); uint16_t tpReadX(void);
uint16_t tpReadY(void); uint16_t tpReadY(void);

View File

@ -49,41 +49,76 @@
#define TOUCHPAD_HAS_PRESSURE FALSE #define TOUCHPAD_HAS_PRESSURE FALSE
#endif #endif
#ifndef TOUCHPAD_SPI_PROLOGUE
#define TOUCHPAD_SPI_PROLOGUE()
#endif
#ifndef TOUCHPAD_SPI_EPILOGUE
#define TOUCHPAD_SPI_EPILOGUE()
#endif
/*===========================================================================*/ /*===========================================================================*/
/* Driver types. */ /* Driver types. */
/*===========================================================================*/ /*===========================================================================*/
typedef struct TOUCHPADDriver TOUCHPADDriver; typedef struct _TOUCHPADDriver TOUCHPADDriver;
/** /**
* @brief Structure representing a Touchpad driver. * @brief Structure representing a Touchpad driver.
*/ */
struct TOUCHPADDriver { struct _TOUCHPADDriver {
/* /*
* @brief Pointer to SPI driver. * @brief Pointer to SPI driver.
*/ * @note SPI driver must be enabled in mcuconf.h and halconf.h
SPIDriver *spid; */
SPIDriver *spip;
/* /*
* @brief SPI configuration. * @brief Pointer to the SPI configuration structure.
*/ * @note The lowest possible speed ~ 1-2MHz is to be used, otherwise
SPIConfig *spicfg; * 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. */ /* External declarations. */
/*===========================================================================*/ /*===========================================================================*/
#if !defined(__DOXYGEN__)
extern TOUCHPADDriver Touchpad;
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Core functions */ /* 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_x(void);
uint16_t tp_lld_read_y(void); uint16_t tp_lld_read_y(void);

View File

@ -69,13 +69,13 @@ static uint16_t _tpReadRealX(void) {
uint32_t results = 0; uint32_t results = 0;
uint16_t i, x; uint16_t i, x;
/* Median filtering is already done in LLD */
for(i = 0; i < CONVERSIONS; i++) { for(i = 0; i < CONVERSIONS; i++) {
tp_lld_read_x(); /* dummy, reduce noise on SPI */
results += tp_lld_read_x(); results += tp_lld_read_x();
} }
// 12-bit /* Take the average of the readings */
x = (((SCREEN_WIDTH-1) * (results/CONVERSIONS)) / 2048); x = results / CONVERSIONS;
return x; return x;
} }
@ -89,13 +89,13 @@ static uint16_t _tpReadRealY(void) {
uint32_t results = 0; uint32_t results = 0;
uint16_t i, y; uint16_t i, y;
/* Median filtering is already done in LLD */
for(i = 0; i < CONVERSIONS; i++) { for(i = 0; i < CONVERSIONS; i++) {
tp_lld_read_y(); /* dummy, reduce noise on SPI */
results += tp_lld_read_y(); results += tp_lld_read_y();
} }
// 12-bit /* Take the average of the readings */
y = (((SCREEN_HEIGHT-1) * (results/CONVERSIONS)) / 2048); y = results / CONVERSIONS;
return y; return y;
} }
@ -135,7 +135,7 @@ static void _tpDrawCross(uint16_t x, uint16_t y) {
* *
* @api * @api
*/ */
void tpInit(TOUCHPADDriver *tp) { void tpInit(const TOUCHPADDriver *tp) {
/* Initialise Mutex */ /* Initialise Mutex */
//MUTEX_INIT //MUTEX_INIT