/** ****************************************************************************** * @file stmpe811.c * @author MCD Application Team * @brief This file provides a set of functions needed to manage the STMPE811 * IO Expander component core drivers. ****************************************************************************** * @attention * *

© Copyright (c) 2014 STMicroelectronics. * All rights reserved.

* * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stmpe811.h" /** @addtogroup BSP * @{ */ /** @addtogroup Components * @{ */ /** @defgroup STMPE811 STMPE811 * @{ */ /** @defgroup STMPE811_Exported_Variables Exported Variables * @{ */ /* Touch screen driver structure initialization */ STMPE811_TS_Mode_t STMPE811_TS_Driver = { STMPE811_TS_Init, STMPE811_DeInit, STMPE811_TS_GestureConfig, STMPE811_ReadID, STMPE811_TS_GetState, STMPE811_TS_GetMultiTouchState, STMPE811_TS_GetGesture, STMPE811_GetCapabilities, STMPE811_TS_EnableIT, STMPE811_TS_DisableIT, STMPE811_TS_ClearIT, STMPE811_TS_ITStatus }; /* IO driver structure initialization */ STMPE811_IO_Mode_t STMPE811_IO_Driver = { STMPE811_IO_Init, STMPE811_DeInit, STMPE811_ReadID, STMPE811_Reset, STMPE811_IO_Start, STMPE811_IO_WritePin, STMPE811_IO_ReadPin, STMPE811_IO_EnableIT, STMPE811_IO_DisableIT, STMPE811_IO_ITStatus, STMPE811_IO_ClearIT, }; /** * @} */ /** @defgroup STMPE811_Private_Function_Prototypes Private Function Prototypes * @{ */ static int32_t STMPE811_EnableGlobalIT(STMPE811_Object_t *pObj); static int32_t STMPE811_DisableGlobalIT(STMPE811_Object_t *pObj); static int32_t STMPE811_TS_DetectTouch(STMPE811_Object_t *pObj); static int32_t STMPE811_EnableITSource(STMPE811_Object_t *pObj, uint8_t Source); static int32_t STMPE811_DisableITSource(STMPE811_Object_t *pObj, uint8_t Source); static int32_t STMPE811_ClearGlobalIT(STMPE811_Object_t *pObj, uint8_t Source); static void STMPE811_Delay(STMPE811_Object_t *pObj, uint32_t Delay); static int32_t STMPE811_ReadRegWrap(void *handle, uint16_t Reg, uint8_t* pData, uint16_t Length); static int32_t STMPE811_WriteRegWrap(void *handle, uint16_t Reg, uint8_t* pData, uint16_t Length); /** * @} */ /** @defgroup STMPE811_Exported_Functions Exported Functions * @{ */ /** * @brief Register IO bus to component object * @param Component object pointer * @retval Component status */ int32_t STMPE811_RegisterBusIO (STMPE811_Object_t *pObj, STMPE811_IO_t *pIO) { int32_t ret; if (pObj == NULL) { ret = STMPE811_ERROR; } else { pObj->IO.Init = pIO->Init; pObj->IO.DeInit = pIO->DeInit; pObj->IO.Address = pIO->Address; pObj->IO.WriteReg = pIO->WriteReg; pObj->IO.ReadReg = pIO->ReadReg; pObj->IO.GetTick = pIO->GetTick; pObj->Ctx.ReadReg = STMPE811_ReadRegWrap; pObj->Ctx.WriteReg = STMPE811_WriteRegWrap; pObj->Ctx.handle = pObj; if(pObj->IO.Init != NULL) { ret = pObj->IO.Init(); } else { ret = STMPE811_ERROR; } } return ret; } /** * @brief Initialize the stmpe811 and configure the needed hardware resources * @param pObj Pointer to component object. * @retval Component status */ int32_t STMPE811_Init(STMPE811_Object_t *pObj) { int32_t ret = STMPE811_OK; if(pObj->IsInitialized == 0U) { /* Initialize IO BUS layer */ pObj->IO.Init(); /* Generate stmpe811 Software reset */ if(STMPE811_Reset(pObj) != STMPE811_OK) { ret = STMPE811_ERROR; } else { pObj->IsInitialized = 1U; } } return ret; } /** * @brief DeInitialize the stmpe811 and un-configure the needed hardware resources * @param pObj Pointer to component object. * @retval Component status */ int32_t STMPE811_DeInit(STMPE811_Object_t *pObj) { if(pObj->IsInitialized == 1U) { /* Generate stmpe811 Software reset */ if(STMPE811_Reset(pObj) != STMPE811_OK) { return STMPE811_ERROR; } else { /* De-Initialize IO BUS layer */ pObj->IO.DeInit(); pObj->IsInitialized = 0U; } } return STMPE811_OK; } /** * @brief Reset the stmpe811 by Software. * @param pObj Pointer to component object. * @retval Component status */ int32_t STMPE811_Reset(STMPE811_Object_t *pObj) { int32_t ret = STMPE811_OK; uint8_t tmp = 2; /* Power Down the stmpe811 */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_SYS_CTRL1_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Wait for a delay to ensure registers erasing */ STMPE811_Delay(pObj, 10); tmp = 0; /* Power On the stmpe811 after the power off => all registers are reinitialized */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_SYS_CTRL1_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Wait for a delay to ensure registers erasing */ STMPE811_Delay(pObj, 2); } } return ret; } /** * @brief Read the STMPE811 IO Expander device ID. * @param pObj Pointer to component object. * @retval The Device ID (two bytes). */ int32_t STMPE811_ReadID(STMPE811_Object_t *pObj, uint32_t *Id) { int32_t ret = STMPE811_OK; uint8_t id_lsb, id_msb; /* Initialize IO BUS layer */ pObj->IO.Init(); if(stmpe811_read_reg(&pObj->Ctx, STMPE811_CHP_ID_LSB_REG, &id_lsb, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else if(stmpe811_read_reg(&pObj->Ctx, STMPE811_CHP_ID_MSB_REG, &id_msb, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Store the device ID value */ *Id = ((uint32_t)id_lsb << 8) | (uint32_t)id_msb; } return ret; } /** * @brief Start the IO functionality use and disable the AF for selected IO pin(s). * @param pObj Pointer to component object. * @param IO_Pin The IO pin(s) to put in AF. This parameter can be one * of the following values: * @arg STMPE811_PIN_x: where x can be from 0 to 7. * @retval Component status */ int32_t STMPE811_IO_Start(STMPE811_Object_t *pObj, uint32_t IO_Pin) { int32_t ret = STMPE811_OK; uint8_t tmp; /* Get the current register value */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_SYS_CTRL2_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Set the Functionalities to be Disabled */ tmp &= ~(STMPE811_IO_FCT | STMPE811_ADC_FCT); /* Write the new register value */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_SYS_CTRL2_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } /* Disable AF for the selected IO pin(s) */ /* Get the current state of the IO_AF register */ else if(stmpe811_read_reg(&pObj->Ctx, STMPE811_IO_AF_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Enable the selected pins alternate function */ tmp |= (uint8_t)IO_Pin; /* Write back the new value in IO AF register */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_AF_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } } return ret; } /** * @brief Configures the IO pin(s) according to IO mode structure value. * @param pObj Pointer to component object. * @param IO_Pin The output pin to be set or reset. This parameter can be one * of the following values: * @arg STMPE811_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 * @arg IO_MODE_IT_LOW_LEVEL * @arg IO_MODE_IT_HIGH_LEVEL * @retval 0 if no error, IO_Mode if error */ int32_t STMPE811_IO_Init(STMPE811_Object_t *pObj, STMPE811_IO_Init_t *IoInit) { int32_t ret = STMPE811_OK; uint8_t tmp; /* IT enable/disable */ switch(IoInit->Mode) { case STMPE811_GPIO_MODE_OFF: case STMPE811_GPIO_MODE_ANALOG: case STMPE811_GPIO_MODE_INPUT: case STMPE811_GPIO_MODE_OUTPUT_OD: case STMPE811_GPIO_MODE_OUTPUT_PP: ret += STMPE811_IO_DisablePinIT(pObj, IoInit->Pin); /* first disable IT */ break; case STMPE811_GPIO_MODE_IT_RISING_EDGE: case STMPE811_GPIO_MODE_IT_FALLING_EDGE: case STMPE811_GPIO_MODE_IT_LOW_LEVEL: case STMPE811_GPIO_MODE_IT_HIGH_LEVEL: ret += STMPE811_IO_EnableIT(pObj); /* first enable IT */ break; default: break; } /* Set direction IN/OUT */ if((IoInit->Mode == STMPE811_GPIO_MODE_OUTPUT_PP) || (IoInit->Mode == STMPE811_GPIO_MODE_OUTPUT_OD)) { ret += STMPE811_IO_InitPin(pObj, IoInit->Pin, STMPE811_GPIO_DIR_OUT); } else { ret += STMPE811_IO_InitPin(pObj, IoInit->Pin, STMPE811_GPIO_DIR_IN); } /* Configure IT mode */ if(IoInit->Mode >= STMPE811_GPIO_MODE_IT_RISING_EDGE) { if(STMPE811_IO_EnableIT(pObj) != STMPE811_OK) { ret = STMPE811_ERROR; } else if(STMPE811_IO_EnablePinIT(pObj, IoInit->Pin) != STMPE811_OK) { ret = STMPE811_ERROR; }/* Get the current register value */ else if(stmpe811_read_reg(&pObj->Ctx, STMPE811_INT_CTRL_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Mask the polarity and type bits */ tmp &= ~(uint8_t)0x06U; /* Modify the Interrupt Output line configuration */ tmp |= (uint8_t)((IoInit->Mode - STMPE811_GPIO_MODE_IT_RISING_EDGE) << 1); /* Set the new register value */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_INT_CTRL_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } } return ret; } /** * @brief Initialize the selected IO pin direction. * @param pObj Pointer to component object. * @param IO_Pin The IO pin to be configured. This parameter could be any * combination of the following values: * @arg STMPE811_PIN_x: Where x can be from 0 to 7. * @param Direction could be STMPE811_GPIO_DIR_IN or STMPE811_GPIO_DIR_OUT. * @retval Component status */ int32_t STMPE811_IO_InitPin(STMPE811_Object_t *pObj, uint32_t IO_Pin, uint8_t Direction) { int32_t ret = STMPE811_OK; uint8_t tmp; /* Get all the Pins direction */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_IO_DIR_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Set the selected pin direction */ if (Direction != STMPE811_GPIO_DIR_IN) { tmp |= (uint8_t)IO_Pin; } else { tmp &= ~(uint8_t)IO_Pin; } /* Write the register new value */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_DIR_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } return ret; } /** * @brief Write a new IO pin state. * @param pObj Pointer to component object. * @param IO_Pin The output pin to be set or reset. This parameter can be one * of the following values: * @arg STMPE811_GPIO_PIN_x: where x can be from 0 to 7. * @param PinState The new IO pin state. * @retval Component status */ int32_t STMPE811_IO_WritePin(STMPE811_Object_t *pObj, uint32_t IO_Pin, uint8_t PinState) { int32_t ret = STMPE811_OK; uint8_t tmp = (uint8_t)IO_Pin; /* Apply the bit value to the selected pin */ if (PinState != 0U) { /* Set the register */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_SET_PIN_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } else { /* Set the register */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_CLR_PIN_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } return ret; } /** * @brief Return the state of the selected IO pin(s). * @param pObj Pointer to component object. * @param IO_Pin The output pin to read its state. This parameter can be one * of the following values: * @arg STMPE811_PIN_x: where x can be from 0 to 7. * @retval STMPE811_ERROR in case of error else IO pin(s) state. */ int32_t STMPE811_IO_ReadPin(STMPE811_Object_t *pObj, uint32_t IO_Pin) { uint8_t tmp; /* Get the current register value */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_IO_MP_STA_REG, &tmp, 1) != STMPE811_OK) { return STMPE811_ERROR; } tmp &= (uint8_t)IO_Pin; return (int32_t)tmp; } /** * @brief Enable the AF for the selected IO pin(s). * @param pObj Pointer to component object. * @param IO_Pin The IO pin to be configured. This parameter could be any * combination of the following values: * @arg STMPE811_PIN_x: Where x can be from 0 to 7. * @retval Component status */ int32_t STMPE811_IO_EnableAF(STMPE811_Object_t *pObj, uint32_t IO_Pin) { int32_t ret = STMPE811_OK; uint8_t tmp; /* Get the current register value */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_IO_AF_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Enable the selected pins alternate function */ tmp &= ~(uint8_t)IO_Pin; /* Write back the new register value */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_AF_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } return ret; } /** * @brief Disable the AF for the selected IO pin(s). * @param pObj Pointer to component object. * @param IO_Pin The IO pin to be configured. This parameter could be any * combination of the following values: * @arg STMPE811_PIN_x: Where x can be from 0 to 7. * @retval Component status */ int32_t STMPE811_IO_DisableAF(STMPE811_Object_t *pObj, uint32_t IO_Pin) { int32_t ret = STMPE811_OK; uint8_t tmp; /* Get the current register value */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_IO_AF_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Disable the selected pins alternate function */ tmp |= (uint8_t)IO_Pin; /* Write back the new register value */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_AF_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } return ret; } /** * @brief Enable the global IO interrupt source. * @param pObj Pointer to component object. * @retval Component status */ int32_t STMPE811_IO_EnableIT(STMPE811_Object_t *pObj) { int32_t ret; /* Enable global IO IT source */ if(STMPE811_EnableITSource(pObj, STMPE811_GIT_IO) != STMPE811_OK) { ret = STMPE811_ERROR; } /* Enable global interrupt */ else if(STMPE811_EnableGlobalIT(pObj) != STMPE811_OK) { ret = STMPE811_ERROR; } else { ret = STMPE811_OK; } return ret; } /** * @brief Disable the global IO interrupt source. * @param pObj Pointer to component object. * @retval Component status */ int32_t STMPE811_IO_DisableIT(STMPE811_Object_t *pObj) { int32_t ret; /* Disable the global interrupt */ if(STMPE811_DisableGlobalIT(pObj) != STMPE811_OK) { ret = STMPE811_ERROR; }/* Disable global IO IT source */ else if(STMPE811_DisableITSource(pObj, STMPE811_GIT_IO) != STMPE811_OK) { ret = STMPE811_ERROR; } else { ret = STMPE811_OK; } return ret; } /** * @brief Enable interrupt mode for the selected IO pin(s). * @param pObj Pointer to component object. * @param IO_Pin The IO interrupt to be enabled. This parameter could be any * combination of the following values: * @arg STMPE811_PIN_x: where x can be from 0 to 7. * @retval Component status */ int32_t STMPE811_IO_EnablePinIT(STMPE811_Object_t *pObj, uint32_t IO_Pin) { int32_t ret = STMPE811_OK; uint8_t tmp; /* Get the IO interrupt state */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_IO_INT_EN_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Set the interrupts to be enabled */ tmp |= (uint8_t)IO_Pin; /* Write the register new value */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_INT_EN_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } return ret; } /** * @brief Disable interrupt mode for the selected IO pin(s). * @param pObj Pointer to component object. * @param IO_Pin The IO interrupt to be disabled. This parameter could be any * combination of the following values: * @arg STMPE811_PIN_x: where x can be from 0 to 7. * @retval Component status */ int32_t STMPE811_IO_DisablePinIT(STMPE811_Object_t *pObj, uint32_t IO_Pin) { int32_t ret = STMPE811_OK; uint8_t tmp; /* Get the IO interrupt state */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_IO_INT_EN_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Set the interrupts to be enabled */ tmp &= ~(uint8_t)IO_Pin; /* Write the register new value */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_INT_EN_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } return ret; } /** * @brief Check the status of the selected IO interrupt pending bit * @param pObj Pointer to component object. * @param IO_Pin The IO interrupt to be checked could be: * @arg STMPE811_PIN_x Where x can be from 0 to 7. * @retval Status of the checked IO pin(s). */ int32_t STMPE811_IO_ITStatus(STMPE811_Object_t *pObj, uint32_t IO_Pin) { uint8_t tmp; /* Get the Interrupt status */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_IO_INT_STA_REG, &tmp, 1) != STMPE811_OK) { return STMPE811_ERROR; } tmp &= (uint8_t)IO_Pin; return (int32_t)tmp; } /** * @brief Clear the selected IO interrupt pending bit(s). * @param pObj Pointer to component object. * @param IO_Pin the IO interrupt to be cleared, could be: * @arg STMPE811_PIN_x: Where x can be from 0 to 7. * @retval Component status */ int32_t STMPE811_IO_ClearIT(STMPE811_Object_t *pObj, uint32_t IO_Pin) { int32_t ret; uint8_t tmp = (uint8_t)IO_Pin; /* Clear the global IO IT pending bit */ if(STMPE811_ClearGlobalIT(pObj, STMPE811_GIT_IO) != STMPE811_OK) { ret = STMPE811_ERROR; } /* Clear the IO IT pending bit(s) */ else if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_INT_STA_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; }/* Clear the Edge detection pending bit*/ else if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_ED_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; }/* Clear the Rising edge pending bit */ else if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_RE_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; }/* Clear the Falling edge pending bit */ else if(stmpe811_write_reg(&pObj->Ctx, STMPE811_IO_FE_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { ret = STMPE811_OK; } return ret; } /** * @brief Configures the touch Screen Controller (Single point detection) * @param pObj Pointer to component object. * @retval Component status. */ int32_t STMPE811_TS_Init(STMPE811_Object_t *pObj) { int32_t ret; uint8_t tmp; ret = STMPE811_Reset(pObj); /* Get the current register value */ ret += stmpe811_read_reg(&pObj->Ctx, STMPE811_SYS_CTRL2_REG, &tmp, 1); /* Set the Functionalities to be Enabled */ tmp &= ~(STMPE811_IO_FCT); /* Write the new register value */ ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_SYS_CTRL2_REG, &tmp, 1); /* Select TSC pins in TSC alternate mode */ ret += STMPE811_IO_EnableAF(pObj, STMPE811_TOUCH_IO_ALL); /* Set the Functionalities to be Enabled */ tmp &= ~(STMPE811_TS_FCT | STMPE811_ADC_FCT); /* Set the new register value */ ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_SYS_CTRL2_REG, &tmp, 1); /* Select Sample Time, bit number and ADC Reference */ tmp = 0x48U; ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_ADC_CTRL1_REG, &tmp, 1); /* Wait for 2 ms */ STMPE811_Delay(pObj, 2); /* Select the ADC clock speed: 3.25 MHz */ tmp = 0x01U; ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_ADC_CTRL2_REG, &tmp, 1); /* Select 2 nF filter capacitor */ /* Configuration: - Touch average control : 4 samples - Touch delay time : 500 uS - Panel driver setting time: 500 uS */ tmp = 0x9AU; ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_TSC_CFG_REG, &tmp, 1); /* Configure the Touch FIFO threshold: single point reading */ tmp = 0x01U; ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_FIFO_TH_REG, &tmp, 1); /* Clear the FIFO memory content. */ ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_FIFO_STA_REG, &tmp, 1); /* Put the FIFO back into operation mode */ tmp = 0x00U; ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_FIFO_STA_REG, &tmp, 1); /* Set the range and accuracy pf the pressure measurement (Z) : - Fractional part :7 - Whole part :1 */ tmp = 0x01U; ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_TSC_FRACT_XYZ_REG, &tmp, 1); /* Set the driving capability (limit) of the device for TSC pins: 50mA */ ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_TSC_I_DRIVE_REG, &tmp, 1); /* Touch screen control configuration (enable TSC): - Window tracking index at 127 - X, Y only acquisition mode */ tmp = 0x73U; ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_TSC_CTRL_REG, &tmp, 1); /* Clear all the status pending bits if any */ tmp = 0xFFU; ret += stmpe811_write_reg(&pObj->Ctx, STMPE811_INT_STA_REG, &tmp, 1); /* Wait for 2 ms delay */ STMPE811_Delay(pObj, 2); if(ret != STMPE811_OK) { ret = STMPE811_ERROR; } return ret; } /** * @brief Configure the STMPE811 gesture * @param pObj Component object pointer * @param GestureInit Gesture init structure * @retval STMPE811_OK */ int32_t STMPE811_TS_GestureConfig(STMPE811_Object_t *pObj, STMPE811_Gesture_Init_t *GestureInit) { /* Feature not supported */ (void)pObj; (void)GestureInit; return STMPE811_ERROR; } /** * @brief Get the touch screen X and Y positions values * @param pObj Pointer to component object. * @param State Single Touch stucture pointer * @retval Component status. */ int32_t STMPE811_TS_GetState(STMPE811_Object_t *pObj, STMPE811_State_t *State) { int32_t ret; int32_t touchDetected; uint8_t tmp, data_xy[3]; uint32_t uldata_xy; touchDetected = STMPE811_TS_DetectTouch(pObj); if(touchDetected > 0) { if(stmpe811_read_reg(&pObj->Ctx, STMPE811_TSC_DATA_NON_INC_REG, data_xy, (uint16_t) sizeof(data_xy)) != STMPE811_OK) { ret = STMPE811_ERROR; } else { State->TouchDetected = 1U; /* Calculate positions values */ uldata_xy = ((uint32_t)data_xy[0] << 16)|((uint32_t)data_xy[1] << 8)| (uint32_t)data_xy[2]; State->TouchX = (uldata_xy >> 12U) & 0x00000FFFU; State->TouchY = uldata_xy & 0x00000FFFU; /* Reset FIFO */ tmp = 0x01U; if(stmpe811_write_reg(&pObj->Ctx, STMPE811_FIFO_STA_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Enable the FIFO again */ tmp = 0x00U; if(stmpe811_write_reg(&pObj->Ctx, STMPE811_FIFO_STA_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { ret = STMPE811_OK; } } } } else if (touchDetected == 0) { State->TouchDetected = 0U; ret = STMPE811_OK; } else { ret = STMPE811_ERROR; } return ret; } /** * @brief Get the touch screen Xn and Yn positions values in multi-touch mode * @param pObj Component object pointer * @param State Multi Touch structure pointer * @retval STMPE811_OK. */ int32_t STMPE811_TS_GetMultiTouchState(STMPE811_Object_t *pObj, STMPE811_MultiTouch_State_t *State) { /* Feature not supported */ (void)pObj; (void)State; return STMPE811_ERROR; } /** * @brief Get Gesture ID * @param pObj Component object pointer * @param GestureId: gesture ID * @retval Gesture ID. */ int32_t STMPE811_TS_GetGesture(STMPE811_Object_t *pObj, uint8_t *GestureId) { /* Feature not supported */ (void)pObj; (void)GestureId; return STMPE811_ERROR; } /** * @brief Configure the selected source to generate a global interrupt or not * @param pObj Pointer to component object. * @retval Component status */ int32_t STMPE811_TS_EnableIT(STMPE811_Object_t *pObj) { int32_t ret; /* Enable TS fifo threshold IT */ if(STMPE811_EnableITSource(pObj, STMPE811_GIT_FTH) != STMPE811_OK) { ret = STMPE811_ERROR; }/* Enable global interrupt */ else if(STMPE811_EnableGlobalIT(pObj) != STMPE811_OK) { ret = STMPE811_ERROR; } else { ret = STMPE811_OK; } return ret; } /** * @brief Configure the selected source to generate a global interrupt or not * @param pObj Pointer to component object. * @retval Component status */ int32_t STMPE811_TS_DisableIT(STMPE811_Object_t *pObj) { int32_t ret; /* Disable global interrupt */ if(STMPE811_DisableGlobalIT(pObj) != STMPE811_OK) { ret = STMPE811_ERROR; }/* Disable TS fifo threshold IT */ else if(STMPE811_DisableITSource(pObj, STMPE811_GIT_FTH) != STMPE811_OK) { ret = STMPE811_ERROR; } else { ret = STMPE811_OK; } return ret; } /** * @brief Configure the selected source to generate a global interrupt or not * @param pObj Pointer to component object. * @retval TS interrupts status */ int32_t STMPE811_TS_ITStatus(STMPE811_Object_t *pObj) { uint8_t tmp; /* Get the Interrupt status */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_INT_STA_REG, &tmp, 1) != STMPE811_OK) { return STMPE811_ERROR; } tmp &= STMPE811_TS_IT; /* Return TS interrupts status */ return (int32_t)tmp; } /** * @brief Configure the selected source to generate a global interrupt or not * @param pObj Pointer to component object. * @retval Component status */ int32_t STMPE811_TS_ClearIT(STMPE811_Object_t *pObj) { /* Clear the global TS IT source */ return STMPE811_ClearGlobalIT(pObj, STMPE811_TS_IT); } /** * @brief Get STMPE811 TouchScreen capabilities * @param pObj Component object pointer * @param Capabilities pointer to STMPE811 TouchScreen capabilities * @retval Component status */ int32_t STMPE811_GetCapabilities(STMPE811_Object_t *pObj, STMPE811_Capabilities_t *Capabilities) { /* Prevent unused argument(s) compilation warning */ (void)(pObj); /* Store component's capabilities */ Capabilities->MultiTouch = 0; Capabilities->Gesture = 0; Capabilities->MaxTouch = STMPE811_MAX_NB_TOUCH; Capabilities->MaxXl = STMPE811_MAX_X_LENGTH; Capabilities->MaxYl = STMPE811_MAX_Y_LENGTH; return STMPE811_OK; } /** * @} */ /** @defgroup STMPE811_Private_Functions Private Functions * @{ */ /** * @brief Enable the Global interrupt. * @param pObj Pointer to component object. * @retval Component status */ static int32_t STMPE811_EnableGlobalIT(STMPE811_Object_t *pObj) { int32_t ret = STMPE811_OK; uint8_t tmp; /* Read the Interrupt Control register */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_INT_CTRL_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Set the global interrupts to be Enabled */ tmp |= (uint8_t)STMPE811_GIT_EN; /* Write Back the Interrupt Control register */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_INT_CTRL_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } return ret; } /** * @brief Disable the Global interrupt. * @param pObj Pointer to component object. * @retval Component status */ static int32_t STMPE811_DisableGlobalIT(STMPE811_Object_t *pObj) { int32_t ret = STMPE811_OK; uint8_t tmp; /* Read the Interrupt Control register */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_INT_CTRL_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Set the global interrupts to be Disabled */ tmp &= ~(uint8_t)STMPE811_GIT_EN; /* Write Back the Interrupt Control register */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_INT_CTRL_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } return ret; } /** * @brief Enable the interrupt mode for the selected IT source * @param pObj Pointer to component object. * @param Source: The interrupt source to be configured, could be: * @arg STMPE811_GIT_IO: IO interrupt * @arg STMPE811_GIT_ADC : ADC interrupt * @arg STMPE811_GIT_FE : Touch Screen Controller FIFO Error interrupt * @arg STMPE811_GIT_FF : Touch Screen Controller FIFO Full interrupt * @arg STMPE811_GIT_FOV : Touch Screen Controller FIFO Overrun interrupt * @arg STMPE811_GIT_FTH : Touch Screen Controller FIFO Threshold interrupt * @arg STMPE811_GIT_TOUCH : Touch Screen Controller Touch Detected interrupt * @retval Component status */ static int32_t STMPE811_EnableITSource(STMPE811_Object_t *pObj, uint8_t Source) { int32_t ret = STMPE811_OK; uint8_t tmp; /* Get the current value of the INT_EN register */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_INT_EN_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Set the interrupts to be Enabled */ tmp |= Source; /* Set the register */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_INT_EN_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } return ret; } /** * @brief Disable the interrupt mode for the selected IT source * @param pObj Pointer to component object. * @param Source: The interrupt source to be configured, could be: * @arg STMPE811_GIT_IO: IO interrupt * @arg STMPE811_GIT_ADC : ADC interrupt * @arg STMPE811_GIT_FE : Touch Screen Controller FIFO Error interrupt * @arg STMPE811_GIT_FF : Touch Screen Controller FIFO Full interrupt * @arg STMPE811_GIT_FOV : Touch Screen Controller FIFO Overrun interrupt * @arg STMPE811_GIT_FTH : Touch Screen Controller FIFO Threshold interrupt * @arg STMPE811_GIT_TOUCH : Touch Screen Controller Touch Detected interrupt * @retval Component status */ static int32_t STMPE811_DisableITSource(STMPE811_Object_t *pObj, uint8_t Source) { int32_t ret = STMPE811_OK; uint8_t tmp; /* Get the current value of the INT_EN register */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_INT_EN_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { /* Set the interrupts to be Enabled */ tmp &= ~Source; /* Set the register */ if(stmpe811_write_reg(&pObj->Ctx, STMPE811_INT_EN_REG, &tmp, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } } return ret; } /** * @brief Clear the selected Global interrupt pending bit(s) * @param pObj Pointer to component object. * @param Source: the Global interrupt source to be cleared, could be any combination * of the following values: * @arg STMPE811_GIT_IO: IO interrupt * @arg STMPE811_GIT_ADC : ADC interrupt * @arg STMPE811_GIT_FE : Touch Screen Controller FIFO Error interrupt * @arg STMPE811_GIT_FF : Touch Screen Controller FIFO Full interrupt * @arg STMPE811_GIT_FOV : Touch Screen Controller FIFO Overrun interrupt * @arg STMPE811_GIT_FTH : Touch Screen Controller FIFO Threshold interrupt * @arg STMPE811_GIT_TOUCH : Touch Screen Controller Touch Detected interrupt * @retval Component status */ static int32_t STMPE811_ClearGlobalIT(STMPE811_Object_t *pObj, uint8_t Source) { /* Write 1 to the bits that have to be cleared */ return stmpe811_write_reg(&pObj->Ctx, STMPE811_INT_STA_REG, &Source, 1); } /** * @brief Return if there is touch detected or not. * @param pObj pointer to component object * @retval Touch detected state. */ static int32_t STMPE811_TS_DetectTouch(STMPE811_Object_t *pObj) { int32_t ret; uint8_t fifo_level; /* Read fifo level */ if(stmpe811_read_reg(&pObj->Ctx, STMPE811_FIFO_SIZE_REG, &fifo_level, 1) != STMPE811_OK) { ret = STMPE811_ERROR; } else { if(fifo_level > 0U) { ret = 1; } else { ret = 0; } } return ret; } /** * @brief This function provides accurate delay (in milliseconds) * @param pObj pointer to component object * @param Delay specifies the delay time length, in milliseconds * @retval STMPE811_OK */ static void STMPE811_Delay(STMPE811_Object_t *pObj, uint32_t Delay) { uint32_t tickstart; tickstart = pObj->IO.GetTick(); while((pObj->IO.GetTick() - tickstart) < Delay) { } } /** * @brief Wrap STMPE811 read function to Bus IO function * @param handle Component object handle * @param Reg The target register address to write * @param pData The target register value to be written * @param Length buffer size to be written * @retval Component status */ static int32_t STMPE811_ReadRegWrap(void *handle, uint16_t Reg, uint8_t* pData, uint16_t Length) { STMPE811_Object_t *pObj = (STMPE811_Object_t *)handle; return pObj->IO.ReadReg(pObj->IO.Address, Reg, pData, Length); } /** * @brief Wrap STMPE811 write function to Bus IO function * @param handle Component object handle * @param Reg The target register address to write * @param pData The target register value to be written * @param Length buffer size to be written * @retval Component status */ static int32_t STMPE811_WriteRegWrap(void *handle, uint16_t Reg, uint8_t* pData, uint16_t Length) { STMPE811_Object_t *pObj = (STMPE811_Object_t *)handle; return pObj->IO.WriteReg(pObj->IO.Address, Reg, pData, Length); } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/