diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-05-06 01:37:47 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-05-06 01:37:47 +0000 |
commit | 42692bfb1645d9c78d7fb358c03aa309a16dfa61 (patch) | |
tree | 5ecc21b8f79c08b4ca93153afc349472a174f81d | |
parent | 5ec5d2ad4dc73eb8235d42f6b823754b53d7223d (diff) | |
download | nuttx-42692bfb1645d9c78d7fb358c03aa309a16dfa61.tar.gz nuttx-42692bfb1645d9c78d7fb358c03aa309a16dfa61.tar.bz2 nuttx-42692bfb1645d9c78d7fb358c03aa309a16dfa61.zip |
Add framework for STMPE11 ADC interfaces
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4702 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r-- | nuttx/drivers/input/Make.defs | 3 | ||||
-rw-r--r-- | nuttx/drivers/input/stmpe11.h | 20 | ||||
-rw-r--r-- | nuttx/drivers/input/stmpe11_adc.c | 259 | ||||
-rw-r--r-- | nuttx/drivers/input/stmpe11_base.c | 17 | ||||
-rw-r--r-- | nuttx/drivers/input/stmpe11_gpio.c | 41 | ||||
-rw-r--r-- | nuttx/include/nuttx/input/stmpe11.h | 61 |
6 files changed, 385 insertions, 16 deletions
diff --git a/nuttx/drivers/input/Make.defs b/nuttx/drivers/input/Make.defs index 5d8d121db..c564eb364 100644 --- a/nuttx/drivers/input/Make.defs +++ b/nuttx/drivers/input/Make.defs @@ -52,6 +52,9 @@ ifeq ($(CONFIG_INPUT_STMPE11),y) ifneq ($(CONFIG_INPUT_STMPE11_GPIO_DISABLE),y) CSRCS += stmpe11_gpio.c endif +ifneq ($(CONFIG_INPUT_STMPE11_ADC_DISABLE),y) + CSRCS += stmpe11_adc.c +endif endif # Include input device driver build support diff --git a/nuttx/drivers/input/stmpe11.h b/nuttx/drivers/input/stmpe11.h index 4bc4ac1d0..c12ad2c22 100644 --- a/nuttx/drivers/input/stmpe11.h +++ b/nuttx/drivers/input/stmpe11.h @@ -76,6 +76,22 @@ #define DEV_FORMAT "/dev/input%d" #define DEV_NAMELEN 16 +/* STMPE11 Resources ************************************************************************/ +#ifndef CONFIG_STMPE11_TSC_DISABLE +# define SMTPE11_ADC_NPINS 4 /* Only pins 0-3 can be used for ADC */ +# define SMTPE11_GPIO_NPINS 4 /* Only pins 0-3 can be used as GPIOs */ +#else +# define SMTPE11_ADC_NPINS 8 /* All pins can be used for ADC */ +# define SMTPE11_GPIO_NPINS 8 /* All pins can be used as GPIOs */ +#endif + +/* Driver flags */ + +#define STMPE11_FLAGS_TSC_INITIALIZED (1 << 0) /* 1: The TSC block has been initialized */ +#define STMPE11_FLAGS_GPIO_INITIALIZED (1 << 1) /* 1: The GIO block has been initialized */ +#define STMPE11_FLAGS_ADC_INITIALIZED (1 << 2) /* 1: The ADC block has been initialized */ +#define STMPE11_FLAGS_TS_INITIALIZED (1 << 3) /* 1: The TS block has been initialized */ + /******************************************************************************************** * Public Types ********************************************************************************************/ @@ -119,6 +135,7 @@ struct stmpe11_dev_s #endif uint8_t inuse; /* SMTPE11 pins in use */ + uint8_t flags; /* See SMTPE11_FLAGS_* definitions */ /* Fields that may be disabled to save size if touchscreen support is not used. */ @@ -151,8 +168,7 @@ struct stmpe11_dev_s /* Fields that may be disabled to save size of GPIO support is not used */ #if !defined(CONFIG_STMPE11_GPIO_DISABLE) && !defined(CONFIG_STMPE11_GPIOINT_DISABLE) - bool initialized; /* True if GPIO interrupt subsystem has been initialized */ - stmpe11_handler_t handlers[8]; /* GPIO "interrupt handlers" */ + stmpe11_handler_t handlers[SMTPE11_GPIO_NPINS]; /* GPIO "interrupt handlers" */ #endif }; diff --git a/nuttx/drivers/input/stmpe11_adc.c b/nuttx/drivers/input/stmpe11_adc.c new file mode 100644 index 000000000..011af9847 --- /dev/null +++ b/nuttx/drivers/input/stmpe11_adc.c @@ -0,0 +1,259 @@ +/**************************************************************************** + * drivers/input/stmpe11_adc.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * References: + * "STMPE811 S-Touch® advanced resistive touchscreen controller with 8-bit + * GPIO expander," Doc ID 14489 Rev 6, CD00186725, STMicroelectronics" + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <unistd.h> +#include <assert.h> +#include <errno.h> +#include <debug.h> + +#include <nuttx/input/stmpe11.h> + +#include "stmpe11.h" + +#if defined(CONFIG_INPUT) && defined(CONFIG_INPUT_STMPE11) && !defined(CONFIG_STMPE11_ADC_DISABLE) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stmpe11_adctiming + * + * Description: + * Configure overall ADC timing that applies to all pins. + * + * Input Parameters: + * handle - The handle previously returned by stmpe11_instantiate + * ctrl1 - The value of the ADC_CRTL1 register (see above). + * ctrl2 - The value of the ADC_CRTL2 register (see above). + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stmpe11_adctiming(STMPE11_HANDLE handle, uint8_t ctrl1, uint8_t ctrl2) +{ + FAR struct stmpe11_dev_s *priv = (FAR struct stmpe11_dev_s *)handle; + uint8_t regval; + int ret; + + DEBUGASSERT(handle); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + int errval = errno; + idbg("sem_wait failed: %d\n", errval); + return -errval; + } + + /* Enable Clocking for ADC */ + + regval = stmpe11_getreg8(priv, STMPE11_SYS_CTRL2); + regval &= ~SYS_CTRL2_ADC_OFF; + stmpe11_putreg8(priv, STMPE11_SYS_CTRL2, regval); + + /* Configure the ADC properties */ + + stmpe11_putreg8(priv, STMPE11_ADC_CTRL1, ctrl1); + stmpe11_putreg8(priv, STMPE11_ADC_CTRL2, ctrl2); + + /* Mark ADC initialized */ + + priv->flags |= STMPE11_FLAGS_ADC_INITIALIZED; + sem_post(&priv->exclsem); + return OK; +} + +/**************************************************************************** + * Name: stmpe11_adcconfig + * + * Description: + * Configure a pin for ADC input. + * + * Input Parameters: + * handle - The handle previously returned by stmpe11_instantiate + * pin - The ADC pin number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stmpe11_adcconfig(STMPE11_HANDLE handle, int pin) +{ + FAR struct stmpe11_dev_s *priv = (FAR struct stmpe11_dev_s *)handle; + uint8_t pinmask = GPIO_PIN(pin); + uint8_t regval; + int ret; + + DEBUGASSERT(handle && (unsigned)pin < STMPE11_ADC_NPINS); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + int errval = errno; + idbg("sem_wait failed: %d\n", errval); + return -errval; + } + + /* Make sure that the pin is not already in use */ + + if ((priv->inuse & pinmask) != 0) + { + idbg("PIN%d is already in-use\n", pin); + sem_post(&priv->exclsem); + return -EBUSY; + } + + /* Clear the alternate function bit for the pin, making it an ADC input + * (or perhaps an an external reference, depending on the state of the + * ADC_CTRL1_REF_SEL bit). + */ + + regval = stmpe11_getreg8(priv, STMPE11_GPIO_AF); + regval &= ~pinmask; + stmpe11_putreg8(priv, STMPE11_GPIO_AF, regval); + + /* Mark the pin as 'in use' */ + + priv->inuse |= pinmask; + sem_post(&priv->exclsem); + return OK; +} + +/**************************************************************************** + * Name: stmpe11_adcread + * + * Description: + * Read the converted analog input value from the select pin. + * + * Input Parameters: + * handle - The handle previously returned by stmpe11_instantiate + * pin - The ADC pin number + * + * Returned Value: + * The converted value (there is no error reporting mechanism). + * + ****************************************************************************/ + +uint16_t stmpe11_adcread(STMPE11_HANDLE handle, int pin) +{ + FAR struct stmpe11_dev_s *priv = (FAR struct stmpe11_dev_s *)handle; + uint8_t pinmask = GPIO_PIN(pin); + uint8_t regval; + int i; + int ret; + + DEBUGASSERT(handle && (unsigned)pin < 8); + + /* Get exclusive access to the device structure */ + + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + int errval = errno; + idbg("sem_wait failed: %d\n", errval); + return -errval; + } + + /* Request AD conversion by setting the bit corresponding the pin in the + * ADC CAPT register. + */ + + stmpe11_putreg8(priv, STMPE11_ADC_CAPT, pinmask); + + /* Wait for the conversion to complete. The ADC CAPT register reads '1' + * if conversion is completed. Reads '0' if conversion is in progress. + * Try three times before giving up. + */ + + for (i = 0; i < 3; i++) + { + /* The worst case ADC conversion time is (nominally) 56.4 uS. The + * following usleep() looks nice but in reality, the usleep() + * does not have that kind of precision (it will probably end up + * waiting 10 MS). + */ + + usleep(57); + + /* Check if the conversion is complete */ + + regval = stmpe11_getreg8(priv, STMPE11_ADC_CAPT); + if ((regval & pinmask) != 0) + { + break; + } + } + + /* At the completion of the conversion, return whatever we read from + * from the channel register associated with the pin. + */ + + return stmpe11_getreg16(priv, STMPE11_ADC_DATACH(pin)); +} + +#endif /* CONFIG_INPUT && CONFIG_INPUT_STMPE11 && !CONFIG_STMPE11_ADC_DISABLE */ + diff --git a/nuttx/drivers/input/stmpe11_base.c b/nuttx/drivers/input/stmpe11_base.c index bfa1a45b8..01268f7b7 100644 --- a/nuttx/drivers/input/stmpe11_base.c +++ b/nuttx/drivers/input/stmpe11_base.c @@ -277,6 +277,7 @@ STMPE11_HANDLE stmpe11_instantiate(FAR struct i2c_dev_s *dev, #endif { FAR struct stmpe11_dev_s *priv; + uint8_t regval; int ret; /* On entry the following is assumed: @@ -329,8 +330,14 @@ STMPE11_HANDLE stmpe11_instantiate(FAR struct i2c_dev_s *dev, stmpe11_reset(priv); - /* Attach the STMPE11 interrupt handler * yet). - */ + /* Configure the interrupt output pin to generate interrupts on high level. */ + + regval = stmpe11_getreg8(priv, STMPE11_INT_CTRL); + regval |= INT_CTRL_INT_POLARITY; /* Pin polarity: Active high */ + regval &= ~INT_CTRL_INT_TYPE; /* Level interrupt */ + stmpe11_putreg8(priv, STMPE11_INT_CTRL, regval); + + /* Attach the STMPE11 interrupt handler. */ config->attach(config, stmpe11_interrupt); @@ -340,6 +347,12 @@ STMPE11_HANDLE stmpe11_instantiate(FAR struct i2c_dev_s *dev, config->clear(config); config->enable(config, true); + /* Enable global interrupts */ + + regval = stmpe11_getreg8(priv, STMPE11_INT_CTRL); + regval |= INT_CTRL_GLOBAL_INT; + stmpe11_putreg8(priv, STMPE11_INT_CTRL, regval); + /* Return our private data structure as an opaque handle */ return (STMPE11_HANDLE)priv; diff --git a/nuttx/drivers/input/stmpe11_gpio.c b/nuttx/drivers/input/stmpe11_gpio.c index 719c0af7c..4fbcc6ca0 100644 --- a/nuttx/drivers/input/stmpe11_gpio.c +++ b/nuttx/drivers/input/stmpe11_gpio.c @@ -43,6 +43,7 @@ #include <nuttx/config.h> +#include <assert.h> #include <errno.h> #include <debug.h> @@ -79,27 +80,33 @@ * ****************************************************************************/ -#ifndef CONFIG_STMPE11_GPIOINT_DISABLE -static inline void stmpe11_gpioinit(FAR struct stmpe11_dev_s *priv) +static void stmpe11_gpioinit(FAR struct stmpe11_dev_s *priv) { uint8_t regval; - if (!priv->initialized) + if ((priv->flags & STMPE11_FLAGS_GPIO_INITIALIZED) == 0) { + /* Enable Clocking for GPIO */ + + regval = stmpe11_getreg8(priv, STMPE11_SYS_CTRL2); + regval &= ~SYS_CTRL2_GPIO_OFF; + stmpe11_putreg8(priv, STMPE11_SYS_CTRL2, regval); + /* Disable all GPIO interrupts */ stmpe11_putreg8(priv, STMPE11_GPIO_EN, 0); /* Enable global GPIO interrupts */ +#ifndef CONFIG_STMPE11_GPIOINT_DISABLE regval = stmpe11_getreg8(priv, STMPE11_INT_EN); regval |= INT_GPIO; stmpe11_putreg8(priv, STMPE11_INT_EN, regval); +#endif - priv->initialized = true; + priv->flags |= STMPE11_FLAGS_GPIO_INITIALIZED; } } -#endif /**************************************************************************** * Public Functions @@ -129,7 +136,7 @@ int stmpe11_gpioconfig(STMPE11_HANDLE handle, uint8_t pinconfig) uint8_t regval; int ret; - DEBUGASSERT(handle && (unsigned)pin < 8); + DEBUGASSERT(handle && (unsigned)pin < STMPE11_GPIO_NPINS); /* Get exclusive access to the device structure */ @@ -150,6 +157,16 @@ int stmpe11_gpioconfig(STMPE11_HANDLE handle, uint8_t pinconfig) return -EBUSY; } + /* Make sure that the GPIO block has been initialized */ + + stmpe11_gpioinit(priv); + + /* Set the alternate function bit for the pin, making it a GPIO */ + + regval = stmpe11_getreg8(priv, STMPE11_GPIO_AF); + regval |= pinmask; + stmpe11_putreg8(priv, STMPE11_GPIO_AF, regval); + /* Is the pin an input or an output? */ if ((pinconfig & STMPE11_GPIO_DIR) == STMPE11_GPIO_OUTPUT) @@ -235,7 +252,7 @@ void stmpe11_gpiowrite(STMPE11_HANDLE handle, uint8_t pinconfig, bool value) int pin = (pinconfig & STMPE11_GPIO_PIN_MASK) >> STMPE11_GPIO_PIN_SHIFT; int ret; - DEBUGASSERT(handle && (unsigned)pin < 8); + DEBUGASSERT(handle && (unsigned)pin < STMPE11_GPIO_NPINS); /* Get exclusive access to the device structure */ @@ -288,7 +305,7 @@ int stmpe11_gpioread(STMPE11_HANDLE handle, uint8_t pinconfig, bool *value) uint8_t regval; int ret; - DEBUGASSERT(handle && (unsigned)pin < 8); + DEBUGASSERT(handle && (unsigned)pin < STMPE11_GPIO_NPINS); /* Get exclusive access to the device structure */ @@ -337,7 +354,7 @@ int stmpe11_gpioattach(STMPE11_HANDLE handle, uint8_t pinconfig, uint8_t regval; int ret; - DEBUGASSERT(handle && (unsigned)pin < 8); + DEBUGASSERT(handle && (unsigned)pin < STMPE11_GPIO_NPINS); /* Get exclusive access to the device structure */ @@ -349,7 +366,7 @@ int stmpe11_gpioattach(STMPE11_HANDLE handle, uint8_t pinconfig, return -errval; } - /* Make sure that the GPIO interrupt system has been initialized */ + /* Make sure that the GPIO interrupt system has been gpioinitialized */ stmpe11_gpioinit(priv); @@ -401,7 +418,7 @@ void stmpe11_gpioint(FAR struct stmpe11_dev_s *priv) /* Look at each pin */ - for (pin = 0; pin < 8; pin++) + for (pin = 0; pin < SMTPE11_GPIO_NPINS; pin++) { pinmask = GPIO_INT(pin); if ((regval & pinmask) != 0) @@ -433,5 +450,5 @@ void stmpe11_gpioint(FAR struct stmpe11_dev_s *priv) } #endif -#endif /* CONFIG_INPUT && CONFIG_INPUT_STMPE11 */ +#endif /* CONFIG_INPUT && CONFIG_INPUT_STMPE11 && !CONFIG_STMPE11_GPIO_DISABLE */ diff --git a/nuttx/include/nuttx/input/stmpe11.h b/nuttx/include/nuttx/input/stmpe11.h index 5bf79e8cd..48cba30a7 100644 --- a/nuttx/include/nuttx/input/stmpe11.h +++ b/nuttx/include/nuttx/input/stmpe11.h @@ -147,6 +147,7 @@ #define STMPE11_ADC_CTRL1 0x20 /* ADC control */ #define STMPE11_ADC_CTRL2 0x21 /* ADC control */ #define STMPE11_ADC_CAPT 0x22 /* To initiate ADC data acquisition */ +#define STMPE11_ADC_DATACH(n) (0x30 + ((n) << 1)) /* ADC channel n (16-bit) */ #define STMPE11_ADC_DATACH0 0x30 /* ADC channel 0 (16-bit) */ #define STMPE11_ADC_DATACH1 0x32 /* ADC channel 1 (16_bit) */ #define STMPE11_ADC_DATACH2 0x34 /* ADC channel 2 (16-bit) */ @@ -598,6 +599,66 @@ EXTERN int stmpe11_gpioattach(STMPE11_HANDLE handle, uint8_t pinconfig, stmpe11_handler_t handler); #endif +/******************************************************************************************** + * Name: stmpe11_adctiming + * + * Description: + * Configure overall ADC timing that applies to all pins. + * + * Input Parameters: + * handle - The handle previously returned by stmpe11_instantiate + * ctrl1 - The value of the ADC_CRTL1 register (see above). + * ctrl2 - The value of the ADC_CRTL2 register (see above). + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ + +#ifndef CONFIG_STMPE11_ADC_DISABLE +EXTERN int stmpe11_adctiming(STMPE11_HANDLE handle, uint8_t ctrl1, uint8_t ctrl2); +#endif + +/******************************************************************************************** + * Name: stmpe11_adcconfig + * + * Description: + * Configure a pin for ADC input. + * + * Input Parameters: + * handle - The handle previously returned by stmpe11_instantiate + * pin - The ADC pin number + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is returned to indicate + * the nature of the failure. + * + ********************************************************************************************/ + +#ifndef CONFIG_STMPE11_ADC_DISABLE +EXTERN int stmpe11_adcconfig(STMPE11_HANDLE handle, int pin); +#endif + +/******************************************************************************************** + * Name: stmpe11_adcread + * + * Description: + * Read the converted analog input value from the select pin. + * + * Input Parameters: + * handle - The handle previously returned by stmpe11_instantiate + * pin - The ADC pin number + * + * Returned Value: + * The converted value (there is no error reporting mechanism). + * + ********************************************************************************************/ + +#ifndef CONFIG_STMPE11_ADC_DISABLE +EXTERN uint16_t stmpe11_adcread(STMPE11_HANDLE handle, int pin); +#endif + #undef EXTERN #ifdef __cplusplus } |