You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/core/embed/trezorhal/stm32u5/touch/sitronix.c

1215 lines
35 KiB

#include STM32_HAL_H
#include TREZOR_BOARD
#include "i2c.h"
/** @addtogroup STM32U5x9J_DISCOVERY
* @{
*/
/** @addtogroup STM32U5x9J_DISCOVERY_BUS
* @{
*/
/** @defgroup STM32U5x9J_DISCOVERY_BUS_Exported_Types BUS Exported Types
* @{
*/
/* Common Error codes */
#define BSP_ERROR_NONE 0
#define BSP_ERROR_NO_INIT -1
#define BSP_ERROR_WRONG_PARAM -2
#define BSP_ERROR_BUSY -3
#define BSP_ERROR_PERIPH_FAILURE -4
#define BSP_ERROR_COMPONENT_FAILURE -5
#define BSP_ERROR_UNKNOWN_FAILURE -6
#define BSP_ERROR_UNKNOWN_COMPONENT -7
#define BSP_ERROR_BUS_FAILURE -8
#define BSP_ERROR_CLOCK_FAILURE -9
#define BSP_ERROR_MSP_FAILURE -10
#define BSP_ERROR_FEATURE_NOT_SUPPORTED -11
/* BSP OSPI error codes */
#define BSP_ERROR_OSPI_SUSPENDED -20
#define BSP_ERROR_OSPI_MMP_UNLOCK_FAILURE -21
#define BSP_ERROR_OSPI_MMP_LOCK_FAILURE -22
/* BSP HSPI error codes */
#define BSP_ERROR_HSPI_MMP_UNLOCK_FAILURE -31
#define BSP_ERROR_HSPI_MMP_LOCK_FAILURE -32
/* BSP BUS error codes */
#define BSP_ERROR_BUS_TRANSACTION_FAILURE -100
#define BSP_ERROR_BUS_ARBITRATION_LOSS -101
#define BSP_ERROR_BUS_ACKNOWLEDGE_FAILURE -102
#define BSP_ERROR_BUS_PROTOCOL_FAILURE -103
#define BSP_ERROR_BUS_MODE_FAULT -104
#define BSP_ERROR_BUS_FRAME_ERROR -105
#define BSP_ERROR_BUS_CRC_ERROR -106
#define BSP_ERROR_BUS_DMA_FAILURE -107
/* TS I2C address */
#define TS_I2C_ADDRESS 0xE0U
/*******************************************************************************
* Function Name : sitronix_read_reg
* Description : Generic Reading function. It must be full-filled with either
* I2C or SPI reading functions
* Input : Register Address, length of buffer
* Output : pdata Read
*******************************************************************************/
int32_t sitronix_read_reg(uint8_t reg, uint8_t *pdata, uint16_t length) {
return i2c_mem_read(TOUCH_I2C_NUM, TS_I2C_ADDRESS, reg, length, pdata, length,
1000);
}
/*******************************************************************************
* Function Name : sitronix_write_reg
* Description : Generic Writing function. It must be full-filled with either
* I2C or SPI writing function
* Input : Register Address, pdata to be written, length of buffer
* Output : None
*******************************************************************************/
int32_t sitronix_write_reg(uint8_t reg, uint8_t *pdata, uint16_t length) {
return i2c_mem_write(TOUCH_I2C_NUM, TS_I2C_ADDRESS, reg, length, pdata,
length, 1000);
}
/*******************************************************************************
* Function Name : sitronix_read_data
* Description : Generic Reading function. It must be full-filled with either
* I2C or SPI reading functions
* Input : Register Address, length of buffer
* Output : pdata Read
*******************************************************************************/
int32_t sitronix_read_data(uint8_t *pdata, uint16_t length) {
return i2c_receive(TOUCH_I2C_NUM, TS_I2C_ADDRESS, pdata, length, 1000);
}
/* Includes ------------------------------------------------------------------*/
/* Macros --------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define SITRONIX_MAX_X_LENGTH 480U
#define SITRONIX_MAX_Y_LENGTH 480U
/** @defgroup SITRONIX_Exported_Constants SITRONIX Exported Constants
* @{
*/
#define SITRONIX_OK (0)
#define SITRONIX_ERROR (-1)
/* Max detectable simultaneous touches */
#define SITRONIX_MAX_DETECTABLE_TOUCH 10U
/* Touch FT6XX6 IDs */
#define SITRONIX_ID 0x02U
/* Values Pn_XH and Pn_YH related */
#define SITRONIX_TOUCH_EVT_FLAG_PRESS_DOWN 0x20U
#define SITRONIX_TOUCH_EVT_FLAG_LIFT_UP 0x60U
#define SITRONIX_TOUCH_EVT_FLAG_CONTACT 0x80U
#define SITRONIX_TOUCH_EVT_FLAG_NO_EVENT 0x00U
#define SITRONIX_TOUCH_POS_MSB_MASK 0x07U
#define SITRONIX_TOUCH_POS_LSB_MASK 0x70U
/* Point 1 registers */
#define SITRONIX_P1_XH_REG 0x09U
#define SITRONIX_P1_XL_REG 0x0AU
#define SITRONIX_P1_YH_REG 0x0BU
#define SITRONIX_P1_YL_REG 0x0CU
/**
* @}
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup SITRONIX_Exported_Types SITRONIX Exported Types
* @{
*/
typedef struct {
uint32_t Radian;
uint32_t OffsetLeftRight;
uint32_t OffsetUpDown;
uint32_t DistanceLeftRight;
uint32_t DistanceUpDown;
uint32_t DistanceZoom;
} SITRONIX_Gesture_Init_t;
typedef struct {
uint32_t TouchDetected;
uint32_t TouchX;
uint32_t TouchY;
} SITRONIX_State_t;
typedef struct {
uint32_t TouchDetected;
uint32_t TouchX[SITRONIX_MAX_DETECTABLE_TOUCH];
uint32_t TouchY[SITRONIX_MAX_DETECTABLE_TOUCH];
uint32_t TouchWeight[SITRONIX_MAX_DETECTABLE_TOUCH];
uint32_t TouchEvent[SITRONIX_MAX_DETECTABLE_TOUCH];
uint32_t TouchArea[SITRONIX_MAX_DETECTABLE_TOUCH];
} SITRONIX_MultiTouch_State_t;
typedef struct {
uint8_t IsInitialized;
} SITRONIX_Object_t;
typedef struct {
uint8_t MultiTouch;
uint8_t Gesture;
uint8_t MaxTouch;
uint32_t MaxXl;
uint32_t MaxYl;
} SITRONIX_Capabilities_t;
typedef struct {
int32_t (*Init)(SITRONIX_Object_t *);
int32_t (*DeInit)(SITRONIX_Object_t *);
int32_t (*GestureConfig)(SITRONIX_Object_t *, SITRONIX_Gesture_Init_t *);
int32_t (*ReadID)(SITRONIX_Object_t *, uint32_t *);
int32_t (*GetState)(SITRONIX_Object_t *, SITRONIX_State_t *);
int32_t (*GetMultiTouchState)(SITRONIX_Object_t *,
SITRONIX_MultiTouch_State_t *);
int32_t (*GetGesture)(SITRONIX_Object_t *, uint8_t *);
int32_t (*GetCapabilities)(SITRONIX_Object_t *, SITRONIX_Capabilities_t *);
int32_t (*EnableIT)(SITRONIX_Object_t *);
int32_t (*DisableIT)(SITRONIX_Object_t *);
int32_t (*ClearIT)(SITRONIX_Object_t *);
int32_t (*ITStatus)(SITRONIX_Object_t *);
} SITRONIX_TS_Drv_t;
int32_t SITRONIX_Init(SITRONIX_Object_t *pObj);
int32_t SITRONIX_DeInit(SITRONIX_Object_t *pObj);
int32_t SITRONIX_GestureConfig(SITRONIX_Object_t *pObj,
SITRONIX_Gesture_Init_t *GestureInit);
int32_t SITRONIX_ReadID(SITRONIX_Object_t *pObj, uint32_t *Id);
int32_t SITRONIX_GetState(SITRONIX_Object_t *pObj, SITRONIX_State_t *State);
int32_t SITRONIX_GetMultiTouchState(SITRONIX_Object_t *pObj,
SITRONIX_MultiTouch_State_t *State);
int32_t SITRONIX_GetGesture(SITRONIX_Object_t *pObj, uint8_t *GestureId);
int32_t SITRONIX_EnableIT(SITRONIX_Object_t *pObj);
int32_t SITRONIX_DisableIT(SITRONIX_Object_t *pObj);
int32_t SITRONIX_ITStatus(SITRONIX_Object_t *pObj);
int32_t SITRONIX_ClearIT(SITRONIX_Object_t *pObj);
int32_t SITRONIX_GetCapabilities(SITRONIX_Object_t *pObj,
SITRONIX_Capabilities_t *Capabilities);
/* Touch screen driver structure initialization */
SITRONIX_TS_Drv_t SITRONIX_TS_Driver = {
SITRONIX_Init, SITRONIX_DeInit, SITRONIX_GestureConfig,
SITRONIX_ReadID, SITRONIX_GetState, SITRONIX_GetMultiTouchState,
SITRONIX_GetGesture, SITRONIX_GetCapabilities, SITRONIX_EnableIT,
SITRONIX_DisableIT, SITRONIX_ClearIT, SITRONIX_ITStatus};
/**
* @}
*/
/** @defgroup SITRONIX_Private_Function_Prototypes SITRONIX Private Function
* Prototypes
* @{
*/
#if (SITRONIX_AUTO_CALIBRATION_ENABLED == 1)
static int32_t SITRONIX_TS_Calibration(SITRONIX_Object_t *pObj);
static int32_t SITRONIX_Delay(SITRONIX_Object_t *pObj, uint32_t Delay);
#endif /* SITRONIX_AUTO_CALIBRATION_ENABLED == 1 */
static int32_t SITRONIX_DetectTouch(SITRONIX_Object_t *pObj);
// static int32_t ReadRegWrap(void *handle, uint8_t Reg, uint8_t *Data,
// uint16_t Length);
// static int32_t WriteRegWrap(void *handle, uint8_t Reg, uint8_t *Data,
// uint16_t Length);
// static int32_t ReadDataWrap(void *handle, uint8_t *pData, uint16_t Length);
/**
* @}
*/
/** @defgroup SITRONIX_Exported_Functions SITRONIX Exported Functions
* @{
*/
/**
* @brief Get SITRONIX sensor capabilities
* @param pObj Component object pointer
* @param Capabilities pointer to SITRONIX sensor capabilities
* @retval Component status
*/
int32_t SITRONIX_GetCapabilities(SITRONIX_Object_t *pObj,
SITRONIX_Capabilities_t *Capabilities) {
/* Prevent unused argument(s) compilation warning */
(void)(pObj);
/* Store component's capabilities */
Capabilities->MultiTouch = 1;
Capabilities->Gesture =
0; /* Gesture feature is currently not activated on FW chipset */
Capabilities->MaxTouch = SITRONIX_MAX_DETECTABLE_TOUCH;
Capabilities->MaxXl = SITRONIX_MAX_X_LENGTH;
Capabilities->MaxYl = SITRONIX_MAX_Y_LENGTH;
return SITRONIX_OK;
}
/**
* @brief Initialize the SITRONIX communication bus
* from MCU to SITRONIX : ie I2C channel initialization (if required).
* @param pObj Component object pointer
* @retval Component status
*/
int32_t SITRONIX_Init(SITRONIX_Object_t *pObj) {
int32_t ret = SITRONIX_OK;
uint8_t data[28U];
if (pObj->IsInitialized == 0U) {
if (sitronix_read_data(data, (uint16_t)sizeof(data)) != SITRONIX_OK) {
ret = SITRONIX_ERROR;
}
pObj->IsInitialized = 1;
}
if (ret != SITRONIX_OK) {
ret = SITRONIX_ERROR;
}
return ret;
}
/**
* @brief De-Initialize the SITRONIX communication bus
* from MCU to SITRONIX : ie I2C channel initialization (if required).
* @param pObj Component object pointer
* @retval Component status
*/
int32_t SITRONIX_DeInit(SITRONIX_Object_t *pObj) {
if (pObj->IsInitialized == 1U) {
pObj->IsInitialized = 0;
}
return SITRONIX_OK;
}
/**
* @brief Configure the SITRONIX gesture
* from MCU to SITRONIX : ie I2C channel initialization (if required).
* @param pObj Component object pointer
* @param GestureInit Gesture init structure
* @retval Component status
*/
int32_t SITRONIX_GestureConfig(SITRONIX_Object_t *pObj,
SITRONIX_Gesture_Init_t *GestureInit) {
return SITRONIX_ERROR;
}
/**
* @brief Read the SITRONIX device ID, pre initialize I2C in case of need to be
* able to read the SITRONIX device ID, and verify this is a SITRONIX.
* @param pObj Component object pointer
* @param Id Pointer to component's ID
* @retval Component status
*/
int32_t SITRONIX_ReadID(SITRONIX_Object_t *pObj, uint32_t *Id) {
int32_t ret = SITRONIX_OK;
uint8_t data[28];
uint8_t trial = 0;
for (trial = 0; trial < 10; trial++) {
if (sitronix_read_data(data, 28) != SITRONIX_OK) {
ret = SITRONIX_ERROR;
} else {
if ((uint32_t)data[0] == SITRONIX_ID) {
*Id = (uint32_t)data[0];
return ret;
}
}
}
return ret;
}
uint8_t sitronix_touching = 0;
/**
* @brief Get the touch screen X and Y positions values
* @param pObj Component object pointer
* @param State Single Touch structure pointer
* @retval Component status.
*/
int32_t SITRONIX_GetState(SITRONIX_Object_t *pObj, SITRONIX_State_t *State) {
int32_t ret = SITRONIX_OK;
uint8_t data[64];
State->TouchDetected = (uint32_t)SITRONIX_DetectTouch(pObj);
if (sitronix_read_data(data, (uint16_t)sizeof(data)) != SITRONIX_OK) {
ret = SITRONIX_ERROR;
} else {
if ((uint32_t)data[2] & 0x80) {
sitronix_touching = 1;
} else {
sitronix_touching = 0;
}
State->TouchX = (((uint32_t)data[2] & SITRONIX_TOUCH_POS_LSB_MASK) << 4);
/* Send back first ready X position to caller */
State->TouchX = ((((uint32_t)data[2] & SITRONIX_TOUCH_POS_LSB_MASK) << 4) |
((uint32_t)data[3]));
/* Send back first ready Y position to caller */
State->TouchY = (((uint32_t)data[2] & SITRONIX_TOUCH_POS_MSB_MASK) << 8) |
((uint32_t)data[4]);
}
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 Component status.
*/
int32_t SITRONIX_GetMultiTouchState(SITRONIX_Object_t *pObj,
SITRONIX_MultiTouch_State_t *State) {
int32_t ret = SITRONIX_OK;
uint8_t data[28];
State->TouchDetected = (uint32_t)SITRONIX_DetectTouch(pObj);
if (sitronix_read_reg(SITRONIX_P1_XH_REG, data, (uint16_t)sizeof(data)) !=
SITRONIX_OK) {
ret = SITRONIX_ERROR;
} else {
/* To be implemented */
}
return ret;
}
/**
* @brief Get Gesture ID
* @param pObj Component object pointer
* @param GestureId gesture ID
* @retval Component status
*/
int32_t SITRONIX_GetGesture(SITRONIX_Object_t *pObj, uint8_t *GestureId) {
/* Prevent unused argument(s) compilation warning */
(void)(pObj);
/* Always return SITRONIX_OK as feature not supported by SITRONIX */
return SITRONIX_ERROR;
}
/**
* @brief Configure the SITRONIX device to generate IT on given INT pin
* connected to MCU as EXTI.
* @param pObj Component object pointer
* @retval Component status
*/
int32_t SITRONIX_EnableIT(SITRONIX_Object_t *pObj) {
/* Prevent unused argument(s) compilation warning */
(void)(pObj);
/* Always return SITRONIX_OK as feature not supported by SITRONIX */
return SITRONIX_ERROR;
}
/**
* @brief Configure the SITRONIX device to stop generating IT on the given INT
* pin connected to MCU as EXTI.
* @param pObj Component object pointer
* @retval Component status
*/
int32_t SITRONIX_DisableIT(SITRONIX_Object_t *pObj) {
/* Prevent unused argument(s) compilation warning */
(void)(pObj);
/* Always return SITRONIX_OK as feature not supported by SITRONIX */
return SITRONIX_ERROR;
}
/**
* @brief Get IT status from SITRONIX interrupt status registers
* Should be called Following an EXTI coming to the MCU to know the
* detailed reason of the interrupt.
* @note : This feature is not supported by SITRONIX.
* @param pObj Component object pointer
* @retval Component status
*/
int32_t SITRONIX_ITStatus(SITRONIX_Object_t *pObj) {
/* Prevent unused argument(s) compilation warning */
(void)(pObj);
/* Always return SITRONIX_OK as feature not supported by SITRONIX */
return SITRONIX_ERROR;
}
/**
* @brief Clear IT status in SITRONIX interrupt status clear registers
* Should be called Following an EXTI coming to the MCU.
* @note : This feature is not supported by SITRONIX.
* @param pObj Component object pointer
* @retval Component status
*/
int32_t SITRONIX_ClearIT(SITRONIX_Object_t *pObj) {
/* Prevent unused argument(s) compilation warning */
(void)(pObj);
/* Always return SITRONIX_OK as feature not supported by SITRONIX */
return SITRONIX_ERROR;
}
/**
* @}
*/
/** @defgroup SITRONIX_Private_Functions SITRONIX Private Functions
* @{
*/
/**
* @brief Return if there is touches detected or not.
* Try to detect new touches and forget the old ones (reset internal
* global variables).
* @param pObj Component object pointer
* @retval Number of active touches detected (can be between 0 and10) or
* SITRONIX_ERROR in case of error
*/
__attribute__((optimize("-O0"))) int32_t SITRONIX_DetectTouch(
SITRONIX_Object_t *pObj) {
int32_t ret;
uint8_t nb_touch = 0;
static uint8_t first_event = 0;
uint8_t data[28];
if (sitronix_read_data((uint8_t *)&data, 28) != SITRONIX_OK) {
ret = SITRONIX_ERROR;
} else {
if (first_event == 0) {
if ((data[0] == 0x09)) {
nb_touch = 1;
first_event = 1;
} else {
nb_touch = 0;
}
} else {
if (data[8] == 0x60) {
nb_touch = 0;
} else {
nb_touch = 1;
}
}
ret = (int32_t)nb_touch;
}
return ret;
}
//
///**
// * @brief Wrap IO bus read function to component register red function
// * @param handle Component object handle
// * @param Reg The target register address to read
// * @param pData The target register value to be read
// * @param Length buffer size to be read
// * @retval Component status.
// */
// static int32_t ReadRegWrap(void *handle, uint8_t Reg, uint8_t *pData,
// uint16_t Length) {
// return i2c_mem_read(TOUCH_I2C_NUM, TS_I2C_ADDRESS, Reg, Length, pData,
// Length, 1000);
//}
//
///**
// * @brief Wrap IO bus write function to component register write 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 WriteRegWrap(void *handle, uint8_t Reg, uint8_t *pData,
// uint16_t Length) {
// return i2c_mem_write(TOUCH_I2C_NUM, TS_I2C_ADDRESS, Reg, Length, pData,
// Length, 1000);
//}
//
///**
// * @brief Wrap IO bus read function to component register red function
// * @param handle Component object handle
// * @param pData The target register value to be read
// * @param Length buffer size to be read
// * @retval Component status.
// */
// static int32_t ReadDataWrap(void *handle, uint8_t *pData, uint16_t Length) {
// return i2c_receive(TOUCH_I2C_NUM, TS_I2C_ADDRESS, pData, Length, 1000);
//}
/**
******************************************************************************
* @file stm32u5x9j_discovery_ts.c
* @author MCD Application Team
* @brief This file provides a set of functions needed to manage the Touch
* Screen on STM32U5x9J-DISCOVERY board.
@verbatim
1. How To use this driver:
--------------------------
- This driver is used to drive the touch screen module of the
STM32U5x9J-DISCOVERY board on the LCD mounted on MB1829A daughter board. The
touch screen driver IC is a SITRONIX.
2. Driver description:
---------------------
+ Initialization steps:
o Initialize the TS using the BSP_TS_Init() function. You can select
display orientation with "Orientation" parameter of TS_Init_t structure
(portrait, landscape, portrait with 180 degrees rotation or landscape
with 180 degrees rotation). The LCD size properties (width and height)
are also parameters of TS_Init_t and depend on the orientation
selected.
+ Touch screen use
o Call BSP_TS_EnableIT() (BSP_TS_DisableIT()) to enable (disable) touch
screen interrupt. BSP_TS_Callback() is called when TS interrupt occurs.
o Call BSP_TS_GetState() to get the current touch status (detection and
coordinates).
o Call BSP_TS_Set_Orientation() to change the current orientation.
Call BSP_TS_Get_Orientation() to get the current orientation.
o Call BSP_TS_GetCapabilities() to get the SITRONIX capabilities.
o SITRONIX doesn't support multi touch and gesture features.
BSP_TS_Get_MultiTouchState(), BSP_TS_GestureConfig() and
BSP_TS_GetGestureId() functions will return
BSP_ERROR_FEATURE_NOT_SUPPORTED.
+ De-initialization steps:
o De-initialize the touch screen using the BSP_TS_DeInit() function.
@endverbatim
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* TS instances */
#define TS_INSTANCES_NBR 1U
#define TS_TOUCH_NBR 10U
/* TS orientations */
#define TS_ORIENTATION_PORTRAIT 0U
#define TS_ORIENTATION_LANDSCAPE 1U
#define TS_ORIENTATION_PORTRAIT_ROT180 2U
#define TS_ORIENTATION_LANDSCAPE_ROT180 3U
/** @defgroup STM32U5x9J_DISCOVERY_TS_Exported_Types TS Exported Types
* @{
*/
typedef struct {
uint32_t Width; /* Screen width */
uint32_t Height; /* Screen height */
uint32_t Orientation; /* Touch screen orientation */
uint32_t Accuracy; /* Expressed in pixel and means the x or y difference vs
old position to consider the new values valid */
} TS_Init_t;
typedef struct {
uint8_t MultiTouch;
uint8_t Gesture;
uint8_t MaxTouch;
uint32_t MaxXl;
uint32_t MaxYl;
} TS_Capabilities_t;
typedef struct {
uint32_t TouchDetected;
uint32_t TouchX;
uint32_t TouchY;
} TS_State_t;
typedef struct {
uint32_t TouchDetected;
uint32_t TouchX[2];
uint32_t TouchY[2];
uint32_t TouchWeight[2];
uint32_t TouchEvent[2];
uint32_t TouchArea[2];
} TS_MultiTouch_State_t;
typedef struct {
uint32_t Radian;
uint32_t OffsetLeftRight;
uint32_t OffsetUpDown;
uint32_t DistanceLeftRight;
uint32_t DistanceUpDown;
uint32_t DistanceZoom;
} TS_Gesture_Config_t;
typedef struct {
uint32_t Width;
uint32_t Height;
uint32_t Orientation;
uint32_t Accuracy;
uint32_t MaxX;
uint32_t MaxY;
uint32_t PreviousX[TS_TOUCH_NBR];
uint32_t PreviousY[TS_TOUCH_NBR];
} TS_Ctx_t;
typedef struct {
int32_t (*Init)(void *);
int32_t (*DeInit)(void *);
int32_t (*GestureConfig)(void *, void *);
int32_t (*ReadID)(void *, uint32_t *);
int32_t (*GetState)(void *, void *);
int32_t (*GetMultiTouchState)(void *, void *);
int32_t (*GetGesture)(void *, void *);
int32_t (*GetCapabilities)(void *, void *);
int32_t (*EnableIT)(void *);
int32_t (*DisableIT)(void *);
int32_t (*ClearIT)(void *);
int32_t (*ITStatus)(void *);
} TS_Drv_t;
/* DSI TS INT pin */
#define TS_INT_PIN GPIO_PIN_8
#define TS_INT_GPIO_PORT GPIOE
#define TS_INT_GPIO_CLK_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()
#define TS_INT_GPIO_CLK_DISABLE() __HAL_RCC_GPIOE_CLK_DISABLE()
#define TS_INT_EXTI_IRQn EXTI8_IRQn
/* Includes ------------------------------------------------------------------*/
//#include "stm32u5x9j_discovery_ts.h"
//#include "stm32u5x9j_discovery.h"
/** @addtogroup BSP
* @{
*/
/** @addtogroup STM32U5x9J_DISCOVERY
* @{
*/
/** @defgroup STM32U5x9J_DISCOVERY_TS TS
* @{
*/
/** @defgroup STM32U5x9J_DISCOVERY_TS_Private_Defines TS Private Defines
* @{
*/
/**
* @}
*/
/** @defgroup STM32U5x9J_DISCOVERY_TS_Private_TypesDefinitions TS Private
* TypesDefinitions
* @{
*/
typedef void (*BSP_EXTI_LineCallback)(void);
/**
* @}
*/
/** @addtogroup STM32U5x9J_DISCOVERY_TS_Exported_Variables TS Exported Variables
* @{
*/
void *Ts_CompObj[TS_INSTANCES_NBR] = {0};
TS_Drv_t *Ts_Drv[TS_INSTANCES_NBR] = {0};
TS_Ctx_t Ts_Ctx[TS_INSTANCES_NBR] = {0};
EXTI_HandleTypeDef hts_exti[TS_INSTANCES_NBR];
IRQn_Type Ts_IRQn[TS_INSTANCES_NBR] = {EXTI15_IRQn};
/**
* @}
*/
/** @defgroup STM32U5x9J_DISCOVERY_TS_Private_FunctionPrototypes TS Private
* Function Prototypes
* @{
*/
static int32_t SITRONIX_Probe(uint32_t Instance);
/**
* @}
*/
/** @addtogroup STM32U5x9J_DISCOVERY_TS_Exported_Functions
* @{
*/
/**
* @brief Initialize the TS.
* @param Instance TS Instance.
* @param TS_Init Pointer to TS initialization structure.
* @retval BSP status.
*/
int32_t BSP_TS_Init(uint32_t Instance, TS_Init_t *TS_Init) {
int32_t status = BSP_ERROR_NONE;
if ((TS_Init == NULL) || (Instance >= TS_INSTANCES_NBR)) {
status = BSP_ERROR_WRONG_PARAM;
} else {
/* Probe the TS driver */
if (SITRONIX_Probe(Instance) != BSP_ERROR_NONE) {
status = BSP_ERROR_COMPONENT_FAILURE;
} else {
TS_Capabilities_t Capabilities;
uint32_t i;
/* Store parameters on TS context */
Ts_Ctx[Instance].Width = TS_Init->Width;
Ts_Ctx[Instance].Height = TS_Init->Height;
Ts_Ctx[Instance].Orientation = TS_Init->Orientation;
Ts_Ctx[Instance].Accuracy = TS_Init->Accuracy;
/* Get capabilities to retrieve maximum values of X and Y */
if (Ts_Drv[Instance]->GetCapabilities(Ts_CompObj[Instance],
&Capabilities) < 0) {
status = BSP_ERROR_COMPONENT_FAILURE;
} else {
/* Store maximum X and Y on context */
Ts_Ctx[Instance].MaxX = Capabilities.MaxXl;
Ts_Ctx[Instance].MaxY = Capabilities.MaxYl;
/* Initialize previous position in order to always detect first touch */
for (i = 0; i < TS_TOUCH_NBR; i++) {
Ts_Ctx[Instance].PreviousX[i] =
TS_Init->Width + TS_Init->Accuracy + 1U;
Ts_Ctx[Instance].PreviousY[i] =
TS_Init->Height + TS_Init->Accuracy + 1U;
}
}
}
}
return status;
}
/**
* @brief De-Initialize the TS.
* @param Instance TS Instance.
* @retval BSP status.
*/
int32_t BSP_TS_DeInit(uint32_t Instance) {
int32_t status = BSP_ERROR_NONE;
if (Instance >= TS_INSTANCES_NBR) {
status = BSP_ERROR_WRONG_PARAM;
} else {
/* De-Init the TS driver */
if (Ts_Drv[Instance]->DeInit(Ts_CompObj[Instance]) < 0) {
status = BSP_ERROR_COMPONENT_FAILURE;
}
}
return status;
}
/**
* @brief Enable the TS interrupt.
* @param Instance TS Instance.
* @retval BSP status.
*/
int32_t BSP_TS_EnableIT(uint32_t Instance) {
/* Prevent unused argument(s) compilation warning */
UNUSED(Instance);
GPIO_InitTypeDef gpio_init_structure;
__HAL_RCC_GPIOE_CLK_ENABLE();
/* Configure Interrupt mode for TS detection pin */
gpio_init_structure.Pin = TS_INT_PIN;
gpio_init_structure.Pull = GPIO_PULLUP;
gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
gpio_init_structure.Mode = GPIO_MODE_IT_FALLING;
HAL_GPIO_Init(TS_INT_GPIO_PORT, &gpio_init_structure);
/* Enable and set Touch screen EXTI Interrupt to the lowest priority */
HAL_NVIC_SetPriority((IRQn_Type)(TS_INT_EXTI_IRQn), 0x0F, 0x00);
HAL_NVIC_EnableIRQ((IRQn_Type)(TS_INT_EXTI_IRQn));
return BSP_ERROR_NONE;
}
/**
* @brief Disable the TS interrupt.
* @param Instance TS Instance.
* @retval BSP status.
*/
int32_t BSP_TS_DisableIT(uint32_t Instance) {
/* Prevent unused argument(s) compilation warning */
UNUSED(Instance);
/* To be Implemented */
return BSP_ERROR_NONE;
}
/**
* @brief Set the TS orientation.
* @param Instance TS Instance.
* @param Orientation TS orientation.
* @retval BSP status.
*/
int32_t BSP_TS_Set_Orientation(uint32_t Instance, uint32_t Orientation) {
int32_t status = BSP_ERROR_NONE;
uint32_t temp;
uint32_t i;
if ((Instance >= TS_INSTANCES_NBR) ||
(Orientation > TS_ORIENTATION_LANDSCAPE_ROT180)) {
status = BSP_ERROR_WRONG_PARAM;
} else {
/* Update TS context if orientation is changed from/to portrait to/from
* landscape */
if ((((Ts_Ctx[Instance].Orientation == TS_ORIENTATION_LANDSCAPE) ||
(Ts_Ctx[Instance].Orientation == TS_ORIENTATION_LANDSCAPE_ROT180)) &&
((Orientation == TS_ORIENTATION_PORTRAIT) ||
(Orientation == TS_ORIENTATION_PORTRAIT_ROT180))) ||
(((Ts_Ctx[Instance].Orientation == TS_ORIENTATION_PORTRAIT) ||
(Ts_Ctx[Instance].Orientation == TS_ORIENTATION_PORTRAIT_ROT180)) &&
((Orientation == TS_ORIENTATION_LANDSCAPE) ||
(Orientation == TS_ORIENTATION_LANDSCAPE_ROT180)))) {
/* Invert width and height */
temp = Ts_Ctx[Instance].Width;
Ts_Ctx[Instance].Width = Ts_Ctx[Instance].Height;
Ts_Ctx[Instance].Height = temp;
/* Invert MaxX and MaxY */
temp = Ts_Ctx[Instance].MaxX;
Ts_Ctx[Instance].MaxX = Ts_Ctx[Instance].MaxY;
Ts_Ctx[Instance].MaxY = temp;
}
/* Store orientation on TS context */
Ts_Ctx[Instance].Orientation = Orientation;
/* Reset previous position */
for (i = 0; i < TS_TOUCH_NBR; i++) {
Ts_Ctx[Instance].PreviousX[i] =
Ts_Ctx[Instance].Width + Ts_Ctx[Instance].Accuracy + 1U;
Ts_Ctx[Instance].PreviousY[i] =
Ts_Ctx[Instance].Height + Ts_Ctx[Instance].Accuracy + 1U;
}
}
return status;
}
/**
* @brief Get the TS orientation.
* @param Instance TS Instance.
* @param Orientation Pointer to TS orientation.
* @retval BSP status.
*/
int32_t BSP_TS_Get_Orientation(uint32_t Instance, uint32_t *Orientation) {
int32_t status = BSP_ERROR_NONE;
if ((Instance >= TS_INSTANCES_NBR) || (Orientation == NULL)) {
status = BSP_ERROR_WRONG_PARAM;
} else {
/* Get orientation from TS context */
*Orientation = Ts_Ctx[Instance].Orientation;
}
return status;
}
/**
* @brief Get position of a single touch.
* @param Instance TS Instance.
* @param TS_State Pointer to single touch structure.
* @retval BSP status.
*/
int32_t BSP_TS_GetState(uint32_t Instance, TS_State_t *TS_State) {
int32_t status = BSP_ERROR_NONE;
uint32_t x_oriented;
uint32_t y_oriented;
uint32_t x_diff;
uint32_t y_diff;
if (Instance >= TS_INSTANCES_NBR) {
status = BSP_ERROR_WRONG_PARAM;
} else {
SITRONIX_State_t state;
/* Get each touch coordinates */
if (Ts_Drv[Instance]->GetState(Ts_CompObj[Instance], &state) < 0) {
status = BSP_ERROR_COMPONENT_FAILURE;
} /* Check and update the number of touches active detected */
else if (state.TouchDetected != 0U) {
x_oriented = /*Ts_Ctx[Instance].MaxX -*/ state.TouchX;
y_oriented = /*Ts_Ctx[Instance].MaxY -*/ state.TouchY;
/* Apply boundary */
TS_State->TouchX =
(x_oriented * Ts_Ctx[Instance].Width) / (Ts_Ctx[Instance].MaxX);
TS_State->TouchY =
(y_oriented * Ts_Ctx[Instance].Height) / (Ts_Ctx[Instance].MaxY);
/* Store Current TS state */
TS_State->TouchDetected = state.TouchDetected;
/* Check accuracy */
x_diff = (TS_State->TouchX > Ts_Ctx[Instance].PreviousX[0])
? (TS_State->TouchX - Ts_Ctx[Instance].PreviousX[0])
: (Ts_Ctx[Instance].PreviousX[0] - TS_State->TouchX);
y_diff = (TS_State->TouchY > Ts_Ctx[Instance].PreviousY[0])
? (TS_State->TouchY - Ts_Ctx[Instance].PreviousY[0])
: (Ts_Ctx[Instance].PreviousY[0] - TS_State->TouchY);
if ((x_diff > Ts_Ctx[Instance].Accuracy) ||
(y_diff > Ts_Ctx[Instance].Accuracy)) {
/* New touch detected */
Ts_Ctx[Instance].PreviousX[0] = TS_State->TouchX;
Ts_Ctx[Instance].PreviousY[0] = TS_State->TouchY;
} else {
TS_State->TouchX = Ts_Ctx[Instance].PreviousX[0];
TS_State->TouchY = Ts_Ctx[Instance].PreviousY[0];
}
} else {
TS_State->TouchDetected = 0U;
TS_State->TouchX = Ts_Ctx[Instance].PreviousX[0];
TS_State->TouchY = Ts_Ctx[Instance].PreviousY[0];
}
}
return status;
}
/**
* @brief Get positions of multiple touch.
* @param Instance TS Instance.
* @param TS_State Pointer to multiple touch structure.
* @retval BSP status.
*/
int32_t BSP_TS_Get_MultiTouchState(const uint32_t Instance,
TS_MultiTouch_State_t *TS_State) {
int32_t status;
UNUSED(TS_State);
if (Instance >= TS_INSTANCES_NBR) {
status = BSP_ERROR_WRONG_PARAM;
} else {
/* Feature not supported in this release */
status = BSP_ERROR_FEATURE_NOT_SUPPORTED;
}
return status;
}
/**
* @brief Configure gesture on TS.
* @param Instance TS Instance.
* @param GestureConfig Pointer to gesture configuration structure.
* @retval BSP status.
*/
int32_t BSP_TS_GestureConfig(const uint32_t Instance,
TS_Gesture_Config_t *GestureConfig) {
int32_t status;
if ((Instance >= TS_INSTANCES_NBR) || (GestureConfig == NULL)) {
status = BSP_ERROR_WRONG_PARAM;
} else {
/* Feature not supported */
status = BSP_ERROR_FEATURE_NOT_SUPPORTED;
}
return status;
}
/**
* @brief Get gesture.
* @param Instance TS Instance.
* @param GestureId Pointer to gesture.
* @retval BSP status.
*/
int32_t BSP_TS_GetGestureId(const uint32_t Instance, uint32_t *GestureId) {
int32_t status;
if ((Instance >= TS_INSTANCES_NBR) || (GestureId == NULL)) {
status = BSP_ERROR_WRONG_PARAM;
} else {
/* Feature not supported */
status = BSP_ERROR_FEATURE_NOT_SUPPORTED;
}
return status;
}
/**
* @brief Get the TS capabilities.
* @param Instance TS Instance.
* @param Capabilities Pointer to TS capabilities structure.
* @retval BSP status.
*/
int32_t BSP_TS_GetCapabilities(uint32_t Instance,
TS_Capabilities_t *Capabilities) {
int32_t status = BSP_ERROR_NONE;
if ((Instance >= TS_INSTANCES_NBR) || (Capabilities == NULL)) {
status = BSP_ERROR_WRONG_PARAM;
} else {
/* Get the TS driver capabilities */
if (Ts_Drv[Instance]->GetCapabilities(Ts_CompObj[Instance], Capabilities) <
0) {
status = BSP_ERROR_COMPONENT_FAILURE;
} else {
/* Update maximum X and Y according orientation */
if ((Ts_Ctx[Instance].Orientation == TS_ORIENTATION_LANDSCAPE) ||
(Ts_Ctx[Instance].Orientation == TS_ORIENTATION_LANDSCAPE_ROT180)) {
uint32_t tmp;
tmp = Capabilities->MaxXl;
Capabilities->MaxXl = Capabilities->MaxYl;
Capabilities->MaxYl = tmp;
}
}
}
return status;
}
/**
* @brief TS Callback.
* @param Instance TS Instance.
* @retval None.
*/
__weak void BSP_TS_Callback(uint32_t Instance) {
/* Prevent unused argument(s) compilation warning */
UNUSED(Instance);
/* This function should be implemented by the user application.
It is called into this driver when an event on TS touch detection */
}
/**
* @brief BSP TS interrupt handler.
* @param Instance TS Instance.
* @retval None.
*/
void BSP_TS_IRQHandler(uint32_t Instance) {
/* Prevent unused argument(s) compilation warning */
UNUSED(Instance);
/* To be implemented */
}
/**
* @}
*/
/** @defgroup STM32U5x9J_DISCOVERY_TS_Private_Functions TS Private Functions
* @{
*/
/**
* @brief Probe the SITRONIX TS driver.
* @param Instance TS Instance.
* @retval BSP status.
*/
static int32_t SITRONIX_Probe(uint32_t Instance) {
int32_t status;
static SITRONIX_Object_t SITRONIXObj;
Ts_CompObj[Instance] = &SITRONIXObj;
Ts_Drv[Instance] = (TS_Drv_t *)&SITRONIX_TS_Driver;
if (Ts_Drv[Instance]->Init(Ts_CompObj[Instance]) < 0) {
status = BSP_ERROR_COMPONENT_FAILURE;
} else {
status = BSP_ERROR_NONE;
}
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#include <string.h>
#include "touch.h"
void touch_init(void) {
TS_Init_t TsInit;
/* Initialize the TouchScreen */
TsInit.Width = 480;
TsInit.Height = 480;
TsInit.Orientation = 0;
TsInit.Accuracy = 10;
BSP_TS_Init(0, &TsInit);
}
void touch_power_on(void) {}
void touch_power_off(void) {}
void touch_sensitivity(uint8_t value) {}
uint32_t touch_is_detected(void) { return sitronix_touching != 0; }
uint32_t touch_read(void) {
TS_State_t state = {0};
static uint32_t xy = 0;
static TS_State_t state_last = {0};
// static uint16_t first = 1;
static uint16_t touching = 0;
BSP_TS_GetState(0, &state);
state.TouchDetected = touch_is_detected();
state.TouchY = state.TouchY > 120 ? state.TouchY - 120 : 0;
state.TouchX = state.TouchX > 120 ? state.TouchX - 120 : 0;
if (!touch_is_detected()) {
// if (state.TouchDetected == 0) {
if (touching) {
// touch end
memcpy(&state_last, &state, sizeof(state));
touching = 0;
return TOUCH_END | xy;
}
return 0;
}
if (state.TouchDetected == 0) {
return 0;
}
// if (first != 0) {
// memcpy(&state_last, &state, sizeof(state));
// first = 0;
// return 0;
// }
if ((state.TouchDetected == 0 && state_last.TouchDetected == 0) ||
memcmp(&state, &state_last, sizeof(state)) == 0) {
// no change detected
return 0;
}
xy = touch_pack_xy(state.TouchX, state.TouchY);
if (state.TouchDetected && !state_last.TouchDetected) {
// touch start
memcpy(&state_last, &state, sizeof(state));
touching = 1;
return TOUCH_START | xy;
} else if (!state.TouchDetected && state_last.TouchDetected) {
// touch end
memcpy(&state_last, &state, sizeof(state));
touching = 0;
return TOUCH_END | xy;
} else {
// touch move
memcpy(&state_last, &state, sizeof(state));
return TOUCH_MOVE | xy;
}
return 0;
}