STM32-Test-01/Core/Src/Lcd/ts_xpt2046.c

230 lines
6.2 KiB
C

/*
* XPT2046 HAL touch driver
* author: Roberto Benjami
* v.2023.04
*
* - software and hardware SPI
*/
#include <stdlib.h>
#include <stdio.h>
//-----------------------------------------------------------------------------
#include "main.h"
#include "lcd.h"
#include "ts.h"
#include "ts_xpt2046.h"
#if defined(STM32H5) || defined(STM32H7) || defined(STM32WBA)
#define TS_SPI_SETBAUDRATE(htsspi, br) MODIFY_REG(htsspi.Instance->CFG1, SPI_CFG1_MBR, br << SPI_CFG1_MBR_Pos)
#else
#define TS_SPI_SETBAUDRATE(htsspi, br) MODIFY_REG(htsspi.Instance->CR1, SPI_CR1_BR, br << SPI_CR1_BR_Pos)
#endif
#if !defined(TS_SPI_HANDLE) || TS_SPI_HANDLE == -1 || TS_CS_MODE == 0
#define TS_CS_ON HAL_GPIO_WritePin(TS_CS_GPIO_Port, TS_CS_Pin, GPIO_PIN_RESET)
#define TS_CS_OFF HAL_GPIO_WritePin(TS_CS_GPIO_Port, TS_CS_Pin, GPIO_PIN_SET)
#elif TS_CS_MODE == 1
#define TS_CS_ON
#define TS_CS_OFF
#endif
//=============================================================================
/* if not used the TS_IRQ pin -> Z1-Z2 touch sensitivy */
#define TS_ZSENS 128
#define TS_SPI_TIMEOUT HAL_MAX_DELAY
#define XPT2046_MODE 0
#define XPT2046_SER 0
#define XPT2046_PD 0
#define XPT2046_CMD_GETTEMP ((1 << 7) | (0 << 4) | (XPT2046_MODE << 3) | (XPT2046_SER << 2) | XPT2046_PD)
#define XPT2046_CMD_GETTVBAT ((1 << 7) | (2 << 4) | (XPT2046_MODE << 3) | (XPT2046_SER << 2) | XPT2046_PD)
#define XPT2046_CMD_GETX ((1 << 7) | (5 << 4) | (XPT2046_MODE << 3) | (XPT2046_SER << 2) | XPT2046_PD)
#define XPT2046_CMD_GETY ((1 << 7) | (1 << 4) | (XPT2046_MODE << 3) | (XPT2046_SER << 2) | XPT2046_PD)
#define XPT2046_CMD_GETZ1 ((1 << 7) | (3 << 4) | (XPT2046_MODE << 3) | (XPT2046_SER << 2) | XPT2046_PD)
#define XPT2046_CMD_GETZ2 ((1 << 7) | (4 << 4) | (XPT2046_MODE << 3) | (XPT2046_SER << 2) | XPT2046_PD)
#define ABS(N) (((N)<0) ? (-(N)) : (N))
//=============================================================================
static uint16_t tx, ty;
//=============================================================================
/* TS chip select pin set */
void xpt2046_ts_Init(uint16_t DeviceAddr);
uint8_t xpt2046_ts_DetectTouch(uint16_t DeviceAddr);
void xpt2046_ts_GetXY(uint16_t DeviceAddr, uint16_t *X, uint16_t *Y);
//=============================================================================
#if defined(__CC_ARM)
#pragma push
#pragma O0
#elif defined(__GNUC__)
#pragma GCC push_options
#pragma GCC optimize("O0")
#endif
void TS_IO_Delay(uint32_t c)
{
while(c--);
}
#if defined(__CC_ARM)
#pragma pop
#elif defined(__GNUC__)
#pragma GCC pop_options
#endif
#if !defined(TS_SPI_HANDLE) || TS_SPI_HANDLE == -1
#if TS_SPI_SPD > 0
#define TS_CLK_DELAY TS_IO_Delay(TS_SPI_SPD);
#else
#define TS_CLK_DELAY
#endif
//-----------------------------------------------------------------------------
uint16_t TS_IO_Transaction(uint8_t cmd)
{
uint16_t ret = 0;
uint32_t i;
TS_CS_ON;
for(i=0; i<8; i++)
{
HAL_GPIO_WritePin(TS_MOSI_GPIO_Port, TS_MOSI_Pin, cmd & 0x80);
TS_CLK_DELAY;
HAL_GPIO_WritePin(TS_SCK_GPIO_Port, TS_SCK_Pin, GPIO_PIN_SET);
TS_CLK_DELAY;
HAL_GPIO_WritePin(TS_SCK_GPIO_Port, TS_SCK_Pin, GPIO_PIN_RESET);
cmd <<= 1;
}
#if XPT2046_READDELAY > 0
TS_IO_Delay(XPT2046_READDELAY);
#endif
HAL_GPIO_WritePin(TS_MOSI_GPIO_Port, TS_MOSI_Pin, GPIO_PIN_RESET);
for(i=0; i<16; i++)
{
ret <<= 1;
TS_CLK_DELAY;
HAL_GPIO_WritePin(TS_SCK_GPIO_Port, TS_SCK_Pin, GPIO_PIN_SET);
if(HAL_GPIO_ReadPin(TS_MISO_GPIO_Port, TS_MISO_Pin))
ret |= 1;
TS_CLK_DELAY;
HAL_GPIO_WritePin(TS_SCK_GPIO_Port, TS_SCK_Pin, GPIO_PIN_RESET);
}
TS_CS_OFF;
return ((ret & 0x7FFF) >> 3);
}
#else
extern SPI_HandleTypeDef TS_SPI_HANDLE;
//-----------------------------------------------------------------------------
uint16_t TS_IO_Transaction(uint8_t cmd)
{
const uint16_t d = 0;
uint16_t ret;
TS_CS_ON;
HAL_SPI_Transmit(&TS_SPI_HANDLE, (uint8_t *)&cmd, 1, TS_SPI_TIMEOUT);
#if XPT2046_READDELAY > 0
TS_IO_Delay(XPT2046_READDELAY);
#endif
HAL_SPI_TransmitReceive(&TS_SPI_HANDLE, (uint8_t *)&d, (uint8_t *)&ret, 2, TS_SPI_TIMEOUT);
TS_CS_OFF;
ret = __REVSH(ret);
return ((ret & 0x7FFF) >> 3);
}
#endif
//-----------------------------------------------------------------------------
/* return:
- 0 : touchscreen is not pressed
- 1 : touchscreen is pressed */
uint8_t TS_IO_DetectToch(void)
{
uint8_t ret;
#if defined(TS_IRQ_GPIO_Port) && defined (TS_IRQ_Pin)
if(HAL_GPIO_ReadPin(TS_IRQ_GPIO_Port, TS_IRQ_Pin))
ret = 0;
else
ret = 1;
#else
if((TS_IO_Transaction(XPT2046_CMD_GETZ1) > TS_ZSENS) || (TS_IO_Transaction(XPT2046_CMD_GETZ2) < (4095 - TS_ZSENS)))
ret = 1;
else
ret = 0;
#endif
return ret;
}
TS_DrvTypeDef xpt2046_ts_drv =
{
xpt2046_ts_Init,
0,
0,
0,
xpt2046_ts_DetectTouch,
xpt2046_ts_GetXY,
0,
0,
0,
0
};
TS_DrvTypeDef *ts_drv = &xpt2046_ts_drv;
//-----------------------------------------------------------------------------
void xpt2046_ts_Init(uint16_t DeviceAddr)
{
#if TS_SPI_HANDLE != -1 && defined(TS_SPI_SPD) && TS_SPI_SPD >= 0 && TS_SPI_SPD <= 7
TS_SPI_SETBAUDRATE(TS_SPI_HANDLE, TS_SPI_SPD);
#endif
}
//-----------------------------------------------------------------------------
uint8_t xpt2046_ts_DetectTouch(uint16_t DeviceAddr)
{
uint8_t ret = 0;
int32_t x1, x2, y1, y2, i;
if(TS_IO_DetectToch())
{
x1 = TS_IO_Transaction(XPT2046_CMD_GETX); /* Get X */
y1 = TS_IO_Transaction(XPT2046_CMD_GETY); /* Get Y */
i = TOUCH_MAXREPEAT;
while(i--)
{
x2 = TS_IO_Transaction(XPT2046_CMD_GETX); /* Get X */
y2 = TS_IO_Transaction(XPT2046_CMD_GETY); /* Get Y */
if((ABS(x1 - x2) < TOUCH_FILTER) && (ABS(y1 - y2) < TOUCH_FILTER))
{
x1 = (x1 + x2) >> 1;
y1 = (y1 + y2) >> 1;
i = 0;
if(TS_IO_DetectToch())
{
tx = x1;
ty = y1;
ret = 1;
}
}
else
{
x1 = x2;
y1 = y2;
}
}
}
return ret;
}
//-----------------------------------------------------------------------------
void xpt2046_ts_GetXY(uint16_t DeviceAddr, uint16_t *X, uint16_t *Y)
{
*X = tx,
*Y = ty;
}