BSP Drivers
Dependencies: CMSIS_STM32L4xx CMSIS_DSP_401 STM32L4xx_HAL_Driver
Diff: Components/stmpe1600/stmpe1600.c
- Revision:
- 0:ad9dfc0179dc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Components/stmpe1600/stmpe1600.c Mon Nov 02 19:38:36 2015 +0000 @@ -0,0 +1,605 @@ +/** + ****************************************************************************** + * @file stmpe1600.c + * @author MCD Application Team + * @version V1.1.0 + * @date 10-February-2015 + * @brief This file provides a set of functions needed to manage the STMPE1600 + * IO Expander devices. + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> + * + * 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 of STMicroelectronics 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 HOLDER 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stmpe1600.h" + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Components + * @{ + */ + +/** @defgroup STMPE1600 + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ + +/** @defgroup STMPE1600_Private_Types_Definitions + * @{ + */ + +/* Private define ------------------------------------------------------------*/ + +/** @defgroup STMPE1600_Private_Defines + * @{ + */ +#define STMPE1600_MAX_INSTANCE 2 + +/* Private macro -------------------------------------------------------------*/ + +/** @defgroup STMPE1600_Private_Macros + * @{ + */ + +/* Private variables ---------------------------------------------------------*/ +static uint16_t tmp = 0; + +/** @defgroup STMPE1600_Private_Variables + * @{ + */ +/* IO driver structure initialization */ +IO_DrvTypeDef stmpe1600_io_drv = +{ + stmpe1600_Init, + stmpe1600_ReadID, + stmpe1600_Reset, + stmpe1600_Start, + stmpe1600_IO_Config, + stmpe1600_IO_WritePin, + stmpe1600_IO_ReadPin, + 0, + 0, + stmpe1600_IO_ITStatus, + stmpe1600_IO_ClearIT, +}; + +uint8_t stmpe1600[STMPE1600_MAX_INSTANCE] = {0}; +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/** @defgroup STMPE1600_Private_Function_Prototypes + * @{ + */ +static uint8_t stmpe1600_GetInstance(uint16_t DeviceAddr); + +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup STMPE1600_Private_Functions + * @{ + */ + +/** + * @brief Initialize the stmpe1600 and configure the needed hardware resources + * @param DeviceAddr: Device address on communication Bus. + * @retval None + */ +void stmpe1600_Init(uint16_t DeviceAddr) +{ + uint8_t instance; + uint8_t empty; + + /* Check if device instance already exists */ + instance = stmpe1600_GetInstance(DeviceAddr); + + if(instance == 0xFF) + { + /* Look for empty instance */ + empty = stmpe1600_GetInstance(0); + + if(empty < STMPE1600_MAX_INSTANCE) + { + /* Register the current device instance */ + stmpe1600[empty] = DeviceAddr; + + /* Initialize IO BUS layer */ + IOE_Init(); + + /* Generate stmpe1600 Software reset */ + stmpe1600_Reset(DeviceAddr); + } + } +} + +/** + * @brief Configures the touch Screen Controller (Single point detection) + * @param DeviceAddr: Device address on communication Bus. + * @retval None. + */ +void stmpe1600_Start(uint16_t DeviceAddr, uint32_t IO_Pin) +{ + /*Configuration already done during the initialization */ +} + +/** + * @brief Reset the stmpe1600 by Software. + * @param DeviceAddr: Device address on communication Bus. + * @retval None + */ +void stmpe1600_Reset(uint16_t DeviceAddr) +{ + /* Power Down the stmpe1600 */ + IOE_Write(DeviceAddr, STMPE1600_REG_SYS_CTRL, (uint16_t)0x80); + + /* Wait for a delay to ensure registers erasing */ + IOE_Delay(2); + + /* Power On the Codec after the power off: all registers are reinitialized */ + IOE_Write(DeviceAddr, STMPE1600_REG_SYS_CTRL, (uint16_t)0x00); + + /* Wait for a delay to ensure registers erasing */ + IOE_Delay(2); +} + +/** + * @brief Read the stmpe1600 device ID. + * @param DeviceAddr: Device address on communication Bus. + * @retval The Device ID (two bytes). + */ +uint16_t stmpe1600_ReadID(uint16_t DeviceAddr) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Initialize IO BUS layer */ + IOE_Init(); + + /* Read the stmpe1600 device ID */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_CHP_ID, tmpData, 2); + + /* Return the device ID value */ + return((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); +} + +/** + * @brief Set the global interrupt Polarity. + * @param DeviceAddr: Device address on communication Bus. + * @param Polarity: could be one of these values; + * @arg STMPE1600_POLARITY_LOW: Interrupt line is active Low/Falling edge + * @arg STMPE1600_POLARITY_HIGH: Interrupt line is active High/Rising edge + * @retval None + */ +void stmpe1600_SetITPolarity(uint16_t DeviceAddr, uint8_t Polarity) +{ + uint8_t tmp = 0; + + /* Get the current register value */ + tmp = IOE_Read(DeviceAddr, STMPE1600_REG_SYS_CTRL); + + /* Mask the polarity bit */ + tmp &= ~(uint16_t)0x01; + + /* Set the Interrupt Output line polarity */ + tmp |= (uint8_t)Polarity; + + /* Set the new register value */ + IOE_Write(DeviceAddr, STMPE1600_REG_SYS_CTRL, tmp); +} + +/** + * @brief Enable the Global interrupt. + * @param DeviceAddr: Device address on communication Bus. + * @retval None + */ +void stmpe1600_EnableGlobalIT(uint16_t DeviceAddr) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Configure NVIC IT for IOE */ + IOE_ITConfig(); + + /* Get the current register value */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_SYS_CTRL, tmpData, 2); + + tmp = ((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); + + /* Set the global interrupts to be Enabled */ + tmp |= (uint16_t)STMPE1600_IT_ENABLE; + + /* Write Back the Interrupt Control register */ + IOE_WriteMultiple(DeviceAddr, STMPE1600_REG_SYS_CTRL, (uint8_t *)&tmp, 2); +} + +/** + * @brief Disable the Global interrupt. + * @param DeviceAddr: Device address on communication Bus. + * @retval None + */ +void stmpe1600_DisableGlobalIT(uint16_t DeviceAddr) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Get the current register value */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_SYS_CTRL, tmpData, 2); + + tmp = ((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); + + /* Set the global interrupts to be Enabled */ + tmp &= ~(uint16_t)STMPE1600_IT_ENABLE; + + /* Write Back the Interrupt Control register */ + IOE_WriteMultiple(DeviceAddr, STMPE1600_REG_SYS_CTRL, (uint8_t *)&tmp, 2); +} + +/** + * @brief Initialize the selected pin(s) direction. + * @param DeviceAddr: Device address on communication Bus. + * @param IO_Pin: IO pin(s) to be configured. + * This parameter could be any combination of the following values: + * @arg STMPE1600_PIN_x: where x can be from 0 to 15. + * @param Direction: could be STMPE1600_DIRECTION_IN or STMPE1600_DIRECTION_OUT. + * @retval None + */ +void stmpe1600_IO_InitPin(uint16_t DeviceAddr, uint32_t IO_Pin, uint8_t Direction) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Get the current register value */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_GPDR, tmpData, 2); + + tmp = ((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); + + /* Set the Pin direction */ + if (Direction != STMPE1600_DIRECTION_IN) + { + tmp |= (uint16_t)IO_Pin; + } + else + { + tmp &= ~(uint16_t)IO_Pin; + } + + /* Set the new register value */ + IOE_WriteMultiple(DeviceAddr, STMPE1600_REG_GPDR, (uint8_t *)&tmp, 2); +} + +/** + * @brief Configure the IO pin(s) according to IO mode structure value. + * @param DeviceAddr: Device address on communication Bus. + * @param IO_Pin: The output pin to be set or reset. This parameter can be one + * of the following values: + * @arg STMPE1600_PIN_x: where x can be from 0 to 7. + * @param IO_Mode: The IO pin mode to configure, could be one of the following values: + * @arg IO_MODE_INPUT + * @arg IO_MODE_OUTPUT + * @arg IO_MODE_IT_RISING_EDGE + * @arg IO_MODE_IT_FALLING_EDGE + * @retval 0 if no error, IO_Mode if error + */ +uint8_t stmpe1600_IO_Config(uint16_t DeviceAddr, uint32_t IO_Pin, IO_ModeTypedef IO_Mode) +{ + uint8_t error_code = 0; + uint8_t buffer[2] = {0,0}; + + /* Configure IO pin according to selected IO mode */ + switch(IO_Mode) + { + case IO_MODE_INPUT: /* Input mode */ + stmpe1600_IO_DisablePinIT(DeviceAddr, IO_Pin); + stmpe1600_IO_InitPin(DeviceAddr, IO_Pin, STMPE1600_DIRECTION_IN); + break; + + case IO_MODE_OUTPUT: /* Output mode */ + stmpe1600_IO_DisablePinIT(DeviceAddr, IO_Pin); + stmpe1600_IO_InitPin(DeviceAddr, IO_Pin, STMPE1600_DIRECTION_OUT); + break; + + case IO_MODE_IT_RISING_EDGE: /* Interrupt rising edge mode */ + stmpe1600_SetITPolarity(DeviceAddr, STMPE1600_POLARITY_HIGH); + stmpe1600_IO_EnablePinIT(DeviceAddr, IO_Pin); + stmpe1600_IO_InitPin(DeviceAddr, IO_Pin, STMPE1600_DIRECTION_IN); + /* Clear all IO IT pending bits if any */ + stmpe1600_IO_ClearIT(DeviceAddr, IO_Pin); + + /* Read GMPR to enable interrupt */ + IOE_ReadMultiple(DeviceAddr , STMPE1600_REG_GPMR, buffer, 2); + break; + + case IO_MODE_IT_FALLING_EDGE: /* Interrupt falling edge mode */ + stmpe1600_SetITPolarity(DeviceAddr, STMPE1600_POLARITY_LOW); + stmpe1600_IO_EnablePinIT(DeviceAddr, IO_Pin); + stmpe1600_IO_InitPin(DeviceAddr, IO_Pin, STMPE1600_DIRECTION_IN); + + /* Clear all IO IT pending bits if any */ + stmpe1600_IO_ClearIT(DeviceAddr, IO_Pin); + + /* Read GMPR to enable interrupt */ + IOE_ReadMultiple(DeviceAddr , STMPE1600_REG_GPMR, buffer, 2); + break; + + default: + error_code = (uint8_t) IO_Mode; + break; + } + return error_code; +} + +/** + * @brief Enable polarity inversion of the selected IO pin(s). + * @param DeviceAddr: Device address on communication Bus. + * @param IO_Pin: IO pin(s) to be configured. + * This parameter could be any combination of the following values: + * @arg STMPE1600_PIN_x: where x can be from 0 to 15. + * @retval None + */ +void stmpe1600_IO_PolarityInv_Enable(uint16_t DeviceAddr, uint32_t IO_Pin) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Get the current register value */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_GPPIR, tmpData, 2); + + tmp = ((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); + + /* Enable pin polarity inversion */ + tmp |= (uint16_t)IO_Pin; + + /* Set the new register value */ + IOE_WriteMultiple(DeviceAddr, STMPE1600_REG_GPPIR, (uint8_t *)&tmp, 2); +} + +/** + * @brief Disable polarity inversion of the selected IO pins. + * @param DeviceAddr: Device address on communication Bus. + * @param IO_Pin: IO pin(s) to be configured. + * This parameter could be any combination of the following values: + * @arg STMPE1600_PIN_x: where x can be from 0 to 15. + * @retval None + */ +void stmpe1600_IO_PolarityInv_Disable(uint16_t DeviceAddr, uint32_t IO_Pin) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Get the current register value */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_GPPIR, tmpData, 2); + + tmp = ((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); + + /* Disable pin polarity inversion */ + tmp &= ~ (uint16_t)IO_Pin; + + /* Set the new register value */ + IOE_WriteMultiple(DeviceAddr, STMPE1600_REG_GPPIR, (uint8_t *)&tmp, 2); +} + +/** + * @brief Set the value of the selected IO pins. + * @param DeviceAddr: Device address on communication Bus. + * @param IO_Pin: IO pin(s) to be set. + * This parameter could be any combination of the following values: + * @arg STMPE1600_PIN_x: where x can be from 0 to 15. + * @param PinState: The value to be set. + * @retval None + */ +void stmpe1600_IO_WritePin(uint16_t DeviceAddr, uint32_t IO_Pin, uint8_t PinState) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Get the current register value */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_GPMR, tmpData, 2); + + tmp = ((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); + + /* Set the pin state */ + if(PinState != 0) + { + tmp |= (uint16_t)IO_Pin; + } + else + { + tmp &= ~(uint16_t)IO_Pin; + } + + /* Set the new register value */ + IOE_WriteMultiple(DeviceAddr, STMPE1600_REG_GPSR, (uint8_t *)&tmp, 2); +} + +/** + * @brief Read the state of the selected IO pin(s). + * @param DeviceAddr: Device address on communication Bus. + * @param IO_Pin: IO pin(s) to be read. + * This parameter could be any combination of the following values: + * @arg STMPE1600_PIN_x: where x can be from 0 to 15. + * @retval State of the selected IO pin(s). + */ +uint32_t stmpe1600_IO_ReadPin(uint16_t DeviceAddr, uint32_t IO_Pin) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Get the register value */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_GPMR, tmpData, 2); + + tmp = ((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); + + /* Return the pin(s) state */ + return(tmp & IO_Pin); +} + +/** + * @brief Enable the interrupt mode for the selected IO pin(s). + * @param DeviceAddr: Device address on communication Bus. + * @param IO_Pin: IO pin(s) to be configured. + * This parameter could be any combination of the following values: + * @arg STMPE1600_PIN_x: where x can be from 0 to 15. + * @retval None + */ +void stmpe1600_IO_EnablePinIT(uint16_t DeviceAddr, uint32_t IO_Pin) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Enable global interrupt */ + stmpe1600_EnableGlobalIT(DeviceAddr); + + /* Get the current register value */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_IEGPIOR, tmpData, 2); + + tmp = ((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); + + /* Put pin in IT mode */ + tmp |= (uint16_t)IO_Pin; + + /* Write the new register value */ + IOE_WriteMultiple(DeviceAddr, STMPE1600_REG_IEGPIOR, (uint8_t *)&tmp, 2); +} + +/** + * @brief Disable the interrupt mode for the selected IO pin(s). + * @param DeviceAddr: Device address on communication Bus. + * @param IO_Pin: IO pin(s) to be configured. + * This parameter could be any combination of the following values: + * @arg STMPE1600_PIN_x: where x can be from 0 to 15. + * @retval None + */ +void stmpe1600_IO_DisablePinIT(uint16_t DeviceAddr, uint32_t IO_Pin) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Get the current register value */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_IEGPIOR, tmpData, 2); + + tmp = ((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); + + /* Disable the IT pin mode */ + tmp &= ~(uint16_t)IO_Pin; + + /* Set the new register value */ + IOE_WriteMultiple(DeviceAddr, STMPE1600_REG_IEGPIOR, (uint8_t *)&tmp, 2); +} + +/** + * @brief Read the IT status of the selected IO pin(s) + * (clears all the pending bits if any). + * @param DeviceAddr: Device address on communication Bus. + * @param IO_Pin: IO pin(s) to be checked. + * This parameter could be any combination of the following values: + * @arg STMPE1600_PIN_x: where x can be from 0 to 15. + * @retval IT Status of the selected IO pin(s). + */ +uint32_t stmpe1600_IO_ITStatus(uint16_t DeviceAddr, uint32_t IO_Pin) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Get the register value */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_ISGPIOR, tmpData, 2); + + tmp = ((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); + + /* Return the pin IT status */ + return((tmp & IO_Pin) == IO_Pin); +} + +/** + * @brief Detect an IT pending bit from the selected IO pin(s). + * (clears all the pending bits if any). + * @param DeviceAddr: Device address on communication Bus. + * @param IO_Pin: IO pin(s) to be checked. + * This parameter could be any combination of the following values: + * @arg STMPE1600_PIN_x: where x can be from 0 to 15. + * @retval IT pending bit detection status. + */ +uint8_t stmpe1600_IO_ReadIT(uint16_t DeviceAddr, uint32_t IO_Pin) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Get the register value */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_ISGPIOR, tmpData, 2); + + tmp = ((uint16_t)tmpData[0] | (((uint16_t)tmpData[1]) << 8)); + + /* Return if there is an IT pending bit or not */ + return(tmp & IO_Pin); +} + +/** + * @brief Clear all the IT pending bits if any. + * @param DeviceAddr: Device address on communication Bus. + * @retval None + */ +void stmpe1600_IO_ClearIT(uint16_t DeviceAddr, uint32_t IO_Pin) +{ + uint8_t tmpData[2] = {0 , 0}; + + /* Get the register value to clear all pending bits */ + IOE_ReadMultiple(DeviceAddr, STMPE1600_REG_ISGPIOR, tmpData, 2); +} + +/** + * @brief Check if the device instance of the selected address is already registered + * and return its index + * @param DeviceAddr: Device address on communication Bus. + * @retval Index of the device instance if registered, 0xFF if not. + */ +static uint8_t stmpe1600_GetInstance(uint16_t DeviceAddr) +{ + uint8_t idx = 0; + + /* Check all the registered instances */ + for(idx = 0; idx < STMPE1600_MAX_INSTANCE ; idx ++) + { + /* Return index if there is address match */ + if(stmpe1600[idx] == DeviceAddr) + { + return idx; + } + } + + return 0xFF; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +