mcu_ab568x/app/platform/gui/ctp/ctp.c
2025-05-30 18:03:10 +08:00

571 lines
17 KiB
C

#include "include.h"
#include "app_variable.h"
#define TRACE_EN 0
#if TRACE_EN
#define TRACE(...) printf(__VA_ARGS__)
#define TRACE_K(...) printk(__VA_ARGS__)
AT(.com_rodata)
const char str_xy[] = "%d: %d, %d\n";
#else
#define TRACE(...)
#define TRACE_K(...)
#endif
//TP相关配置
#define CTP_CNT_SHORT_MOV (GUI_SCREEN_WIDTH / 30) //CTP短划阈值(屏幕距离)
#define CTP_CNT_LONG_MOV (GUI_SCREEN_WIDTH / 3) //CTP长划阈值(屏幕距离)
#define CTP_CNT_LONG 40 //CTP长按时间阈值(CTP INT时钟个数)
#define I2C_WRITE_ADDR(ADDR) ((ADDR) << 1) //CTP IIC写地址
#define I2C_READ_ADDR(ADDR) ((ADDR) << 1 | 1) //CTP IIC读地址
#if SECURITY_PAY_EN
AT(.com_text.ctp_var)
bool ctp_kick_status;
#endif // SECURITY_PAY_EN
enum {
CTP_STA_IDLE,
CTP_STA_PRESS,
CTP_STA_PRESS_LONG,
CTP_STA_MOV_SHORT,
CTP_STA_MOV_LONG,
};
static struct ctp_cb_t {
s32 x; //当前坐标
s32 y;
s32 sx; //起始坐标
s32 sy;
s32 last_dx; //最后一次相对偏移
s32 last_dy;
u8 cnt;
u8 sta;
bool flag_last;
} ctp_cb;
#if CHIP_PACKAGE_QFN40
static i2c_t __CTP_IIC1 = {
.sfr = (i2c_sfr_t *) &IIC1CON0,
.map = (i2c_map_t *) &FUNCMCON2,
};
i2c_t *CTP_IIC = &__CTP_IIC1;
#else
#if (CHIP_PACKAGE_SELECT == CHIP_5682C)
static i2c_t __CTP_IIC1 = {
.sfr = (i2c_sfr_t *) &IIC1CON0,
.map = (i2c_map_t *) &FUNCMCON2,
};
i2c_t *CTP_IIC = &__CTP_IIC1;
#else
static i2c_t __CTP_IIC0 = {
.sfr = (i2c_sfr_t *) &IIC0CON0,
.map = (i2c_map_t *) &FUNCMCON2,
};
i2c_t *CTP_IIC = &__CTP_IIC0;
#endif
#endif
static int ctp_chip_id = 0;
int get_ctp_chip_ID(void)
{
return ctp_chip_id;
}
void set_ctp_chip_ID(int id)
{
ctp_chip_id = id;
}
AT(.com_text.ctp)
void ctp_int_isr(void)
{
if (WKUPEDG & BIT(16 + PORT_CTP_INT_VECTOR))
{
uart_putchar('#');
WKUPCPND = BIT(16 + PORT_CTP_INT_VECTOR);
#if GUI_CTP_COMPATIBLE_DRIVER
if (get_ctp_chip_ID() == CTP_AXS5106_CHIP_ID)
{
AXS5106_read_readkick();
}
else
{
spt5113c_readkick();
}
#else
#if (CTP_SELECT == CTP_CST8X)
ctp_cst8x_readkick();
#elif (CTP_SELECT == CTP_CHSC6X)
ctp_chsc6x_readkick();
#elif (CTP_SELECT == CTP_AXS5106)
AXS5106_read_readkick();
#elif (CTP_SELECT | CTP_SPT5113C)
spt5113c_readkick();
#endif
#endif
}
}
//处理TP的消息
AT(.com_text.ctp)
void ctp_msg_deal(bool press)
{
if (press) {
reset_sleep_delay_all();
int mx, my;
mx = abs_s(ctp_cb.x - ctp_cb.sx);
my = abs_s(ctp_cb.y - ctp_cb.sy);
switch (ctp_cb.sta) {
case CTP_STA_IDLE:
ctp_cb.sta = CTP_STA_PRESS; //按下
ctp_cb.sx = ctp_cb.x;
ctp_cb.sy = ctp_cb.y;
my_msg_enqueue(MSG_CTP_TOUCH); //触摸事件
ctp_cb.cnt++;
break;
case CTP_STA_PRESS:
case CTP_STA_PRESS_LONG:
case CTP_STA_MOV_SHORT:
if (ctp_cb.sta == CTP_STA_PRESS) {
ctp_cb.cnt++;
if (ctp_cb.cnt >= CTP_CNT_LONG) {
my_msg_enqueue(MSG_CTP_LONG); //长按
ctp_cb.sta = CTP_STA_PRESS_LONG;
return;
}
}
if (mx >= my) {
if (mx >= CTP_CNT_LONG_MOV) {
if (ctp_cb.x < ctp_cb.sx) {
if (ctp_cb.sta != CTP_STA_MOV_SHORT) {
my_msg_enqueue(MSG_CTP_SHORT_LEFT); //补发左短划
}
my_msg_enqueue(MSG_CTP_LONG_LEFT); //左长划
ctp_cb.sta = CTP_STA_MOV_LONG;
} else {
if (ctp_cb.sta != CTP_STA_MOV_SHORT) {
my_msg_enqueue(MSG_CTP_SHORT_RIGHT); //补发右短划
}
my_msg_enqueue(MSG_CTP_LONG_RIGHT); //右长划
ctp_cb.sta = CTP_STA_MOV_LONG;
}
return;
}
if (ctp_cb.sta != CTP_STA_MOV_SHORT && mx >= CTP_CNT_SHORT_MOV) {
if (ctp_cb.x < ctp_cb.sx) {
my_msg_enqueue(MSG_CTP_SHORT_LEFT); //左短划
ctp_cb.sta = CTP_STA_MOV_SHORT;
} else {
my_msg_enqueue(MSG_CTP_SHORT_RIGHT); //右短划
ctp_cb.sta = CTP_STA_MOV_SHORT;
}
return;
}
} else {
if (my >= CTP_CNT_LONG_MOV) {
if (ctp_cb.y < ctp_cb.sy) {
if (ctp_cb.sta != CTP_STA_MOV_SHORT) {
my_msg_enqueue(MSG_CTP_SHORT_UP); //补发上短划
}
my_msg_enqueue(MSG_CTP_LONG_UP); //上长划
ctp_cb.sta = CTP_STA_MOV_LONG;
} else {
if (ctp_cb.sta != CTP_STA_MOV_SHORT) {
my_msg_enqueue(MSG_CTP_SHORT_DOWN); //补发下短划
}
my_msg_enqueue(MSG_CTP_LONG_DOWN); //下长划
ctp_cb.sta = CTP_STA_MOV_LONG;
}
return;
}
if (ctp_cb.sta != CTP_STA_MOV_SHORT && my >= CTP_CNT_SHORT_MOV) {
if (ctp_cb.y < ctp_cb.sy) {
my_msg_enqueue(MSG_CTP_SHORT_UP); //上短划
ctp_cb.sta = CTP_STA_MOV_SHORT;
} else {
my_msg_enqueue(MSG_CTP_SHORT_DOWN); //下短划
ctp_cb.sta = CTP_STA_MOV_SHORT;
}
return;
}
}
break;
case CTP_STA_MOV_LONG:
default:
break;
}
} else {
if (ctp_cb.sta == CTP_STA_PRESS) {
my_msg_enqueue(MSG_CTP_CLICK); //单击
} else if (ctp_cb.sta == CTP_STA_PRESS_LONG) {
my_msg_enqueue(MSG_CTP_LONG_LIFT); //长按抬起
}
ctp_cb.cnt = 0;
ctp_cb.sta = CTP_STA_IDLE;
}
}
#if SECURITY_PAY_EN
AT(.com_text.ctp)
bool ctp_get_kick_status(void)
{
return ctp_kick_status;
}
#endif // SECURITY_PAY_EN
AT(.com_text.ctp)
void ctp_isr(void)
{
bool press;
if (CTP_IIC->sfr->IICxCON0 & BIT(31))
{
CTP_IIC->sfr->IICxCON0 |= BIT(29);
s32 last_x = ctp_cb.x;
s32 last_y = ctp_cb.y;
#if GUI_CTP_COMPATIBLE_DRIVER
if (get_ctp_chip_ID() == CTP_AXS5106_CHIP_ID) {
press = AXS5106_get_touch_point(&ctp_cb.x, &ctp_cb.y);
} else {
press = spt5113c_get_point(&ctp_cb.x, &ctp_cb.y);
}
#else
#if (CTP_SELECT == CTP_CST8X)
press = ctp_cst8x_get_point(&ctp_cb.x, &ctp_cb.y);
#elif (CTP_SELECT == CTP_CHSC6X)
press = ctp_chsc6x_get_point(&ctp_cb.x, &ctp_cb.y);
#elif (CTP_SELECT == CTP_AXS5106)
press = AXS5106_get_touch_point(&ctp_cb.x, &ctp_cb.y);
#elif (CTP_SELECT | CTP_SPT5113C)
press = spt5113c_get_point(&ctp_cb.x, &ctp_cb.y);
#endif
#endif
if (press) {
if (ctp_cb.flag_last) {
ctp_cb.last_dx = ctp_cb.x - last_x;
ctp_cb.last_dy = ctp_cb.y - last_y;
} else {
ctp_cb.flag_last = true;
ctp_cb.last_dx = 0;
ctp_cb.last_dy = 0;
}
} else {
ctp_cb.flag_last = false;
}
#if CTP_SUPPORT_COVER
if ((ctp_cb.x == -1)&&(SysVariable.capping_hand_offscreen_flag))
{
my_msg_enqueue(MSG_CTP_COVER); //盖手
}
#endif
TRACE_K(str_xy, press, ctp_cb.x, ctp_cb.y);
ctp_msg_deal(press);
#if SECURITY_PAY_EN
ctp_kick_status = false;
#endif // SECURITY_PAY_EN
}
}
//获取坐标,返回触屏点击状态
AT(.com_text.ctp)
bool ctp_get_cur_point(s32 *sx, s32 *sy, s32 *x, s32 *y)
{
bool press;
GLOBAL_INT_DISABLE();
*sx = ctp_cb.sx;
*sy = ctp_cb.sy;
*x = ctp_cb.x;
*y = ctp_cb.y;
press = (ctp_cb.sta != CTP_STA_IDLE);
GLOBAL_INT_RESTORE();
return press;
}
//获取坐标差量,返回触屏点击状态
AT(.com_text.ctp)
bool ctp_get_dxy(s32 *dx, s32 *dy)
{
bool press;
GLOBAL_INT_DISABLE();
press = (ctp_cb.sta != CTP_STA_IDLE);
if (press) {
*dx = ctp_cb.x - ctp_cb.sx;
*dy = ctp_cb.y - ctp_cb.sy;
}
GLOBAL_INT_RESTORE();
return press;
}
//获取起始X,Y坐标
AT(.com_text.ctp)
point_t ctp_get_sxy(void)
{
point_t pt;
GLOBAL_INT_DISABLE();
pt.x = ctp_cb.sx;
pt.y = ctp_cb.sy;
GLOBAL_INT_RESTORE();
return pt;
}
//获取最后一次偏移
AT(.com_text.ctp)
point_t ctp_get_last_dxy(void)
{
point_t pt;
GLOBAL_INT_DISABLE();
pt.x = ctp_cb.last_dx;
pt.y = ctp_cb.last_dy;
GLOBAL_INT_RESTORE();
return pt;
}
//获取点击XY的相对于控件的坐标
AT(.com_text.ctp)
point_t ctp_get_rxy(widget_t *widget)
{
point_t pt;
rect_t rect = widget_get_absolute(widget);
GLOBAL_INT_DISABLE();
pt.x = (ctp_cb.sx - (rect.x - (rect.wid >> 1)) + (rect.wid >> 1)) >> 1;
pt.y = (ctp_cb.sy - (rect.y - (rect.hei >> 1)) + (rect.hei >> 1)) >> 1;
GLOBAL_INT_RESTORE();
return pt;
}
//读数据KICK
AT(.com_text.ctp)
void ctp_iic_readkick(void *buf, u8 addr, int len)
{
CTP_IIC->sfr->IICxCMDA = (I2C_READ_ADDR(TP_IIC_ADDR) << 24) | (addr << 8) | I2C_WRITE_ADDR(TP_IIC_ADDR); //0x2A
CTP_IIC->sfr->IICxCON1 = BIT(12) | BIT(11) | BIT(9) | BIT(8) | BIT(7) | BIT(5) | BIT(4) | BIT(3);
CTP_IIC->sfr->IICxDMAADR = DMA_ADR(buf);
CTP_IIC->sfr->IICxDMACNT = ((len - 1) << 16) | BIT(0);
CTP_IIC->sfr->IICxCON0 |= BIT(28); //KICK
#if SECURITY_PAY_EN
ctp_kick_status = true;
#endif // SECURITY_PAY_EN
}
//读数据接口(开中断前)
bool ctp_iic_read(void *buf, u8 addr, int len)
{
u32 ticks;
ctp_iic_readkick(buf, addr, len);
ticks = tick_get();
while (!(CTP_IIC->sfr->IICxCON0 & BIT(31))) {
if (tick_check_expire(ticks, 20)) {
return false;
}
}
CTP_IIC->sfr->IICxCON0 |= BIT(29); //Clear Pending
return true;
}
//复位
void ctp_reset(void)
{
PORT_CTP_RST_L();
delay_5ms(2);
PORT_CTP_RST_H();
delay_5ms(21);
}
//初始化
void ctp_init(void)
{
bool res;
memset(&ctp_cb, 0, sizeof(ctp_cb));
//配置时钟
#if CHIP_PACKAGE_QFN40
CLKGAT2 |= BIT(1); //IIC1
CLKCON1 |= BIT(8); //x26m_clkdiv8
RSTCON0 |= BIT(7); //Release CTP_IIC->sfr->IICx
#else
#if (CHIP_PACKAGE_SELECT == CHIP_5682C)
CLKGAT2 |= BIT(1); //IIC1
CLKCON1 |= BIT(8); //x26m_clkdiv8
RSTCON0 |= BIT(7); //Release CTP_IIC->sfr->IICx
#else
CLKGAT2 |= BIT(0); //IIC0
CLKCON1 |= BIT(7); //x26m_clkdiv8
RSTCON0 |= BIT(3); //Release CTP_IIC->sfr->IICx
#endif
#endif
port_ctp_init();
//配置IIC模块
#if (CTP_SELECT | CTP_AXS5106)||(CTP_SELECT | CTP_SPT5113C)
CTP_IIC->sfr->IICxCON0 = BIT(10) | (16 << 4) | BIT(0); //WSCL_OPT, POSDIV, IIC EN 5106 200K 以下能够读到正确的ID
#else
CTP_IIC->sfr->IICxCON0 = BIT(10) | (8 << 4) | BIT(0); //WSCL_OPT, POSDIV, IIC EN
#endif
CTP_IIC->sfr->IICxCON1 = BIT(12) | BIT(11) | BIT(9) | BIT(8) | BIT(7) | BIT(5) | BIT(4) | BIT(3) | 1;
//复位TP/等待模块使能
ctp_reset();
#if GUI_CTP_COMPATIBLE_DRIVER
res = AXS5106_init();
if (!res) {
res = spt5113c_init();
}
#else
#if (CTP_SELECT == CTP_CST8X)
res = ctp_cst8x_init();
#elif (CTP_SELECT == CTP_CHSC6X)
res = ctp_chsc6x_init();
#elif (CTP_SELECT == CTP_AXS5106)
res = AXS5106_init();
#elif (CTP_SELECT | CTP_SPT5113C)
res = spt5113c_init();
#endif
#endif
#if SECURITY_PAY_EN
CTP_IIC->sfr->IICxCON0 = BIT(10) | (26 << 4) | BIT(0); //alipay不支持那么高速率
#endif // SECURITY_PAY_EN
if (!res) {
TRACE("CTP ERROR!\n");
return;
}
//SPT5113C需要延后初始化IRQ信号引脚
if(get_ctp_chip_ID() != CTP_STP5113_CHIP_ID)
{
sys_irq_init(IRQ_CTP_VECTOR, 0, ctp_isr);
CTP_IIC->sfr->IICxCON0 |= BIT(1); //IIC INT EN
//INT信号中断
port_irq_register(PORT_CTP_INT_VECTOR, ctp_int_isr);
port_wakeup_init(PORT_CTP_INT, 1, 1); //开内部上拉, 下降沿唤醒
}
}
//初始化IRQ信号引脚
void ctp_irq_init(void)
{
sys_irq_init(IRQ_CTP_VECTOR, 0, ctp_isr);
CTP_IIC->sfr->IICxCON0 |= BIT(1); //IIC INT EN
//INT信号中断
port_irq_register(PORT_CTP_INT_VECTOR, ctp_int_isr);
port_wakeup_init(PORT_CTP_INT, 1, 1); //开内部上拉, 下降沿唤醒
}
void ctp_exit(void)
{
#if CHIP_PACKAGE_QFN40
CTP_IIC->sfr->IICxCON0 = 0;
RSTCON0 &= ~BIT(7); //reset CTP_IIC->sfr->IICx
CLKGAT2 &= ~BIT(1);
#else
#if (CHIP_PACKAGE_SELECT == CHIP_5682C)
CTP_IIC->sfr->IICxCON0 = 0;
RSTCON0 &= ~BIT(7); //reset CTP_IIC->sfr->IICx
CLKGAT2 &= ~BIT(1);
#else
CTP_IIC->sfr->IICxCON0 = 0;
RSTCON0 &= ~BIT(3); //reset CTP_IIC->sfr->IICx
CLKGAT2 &= ~BIT(0);
#endif
#endif
port_ctp_exit();
port_irq_free(PORT_CTP_INT_VECTOR);
port_wakeup_exit(PORT_CTP_INT);
}
//升级写KICK
void ctp_iic_write_update_kick(u8 dev_addr, u16 addr, u8 *cmd, int len)
{
CTP_IIC->sfr->IICxCMDA = ((addr >> 8) << 8) | I2C_WRITE_ADDR(dev_addr); //2Bytes的reg addr放高位到addr0
u8 buf[8];
buf[0] = addr & 0xff; //2Bytes的reg addr低位放到数据第一字节
if(len > 1) {
memcpy(&buf[1], cmd, len - 1);
}
CTP_IIC->sfr->IICxDMAADR = DMA_ADR(buf);
CTP_IIC->sfr->IICxDMACNT = ((len - 1) << 16) | BIT(1) | BIT(0);
CTP_IIC->sfr->IICxCON0 |= BIT(28); //KICK
delay_ms(2);
}
//升级写
bool ctp_iic_update_write(u8 dev_addr, u16 addr, u8 *cmd, int len)
{
CTP_IIC->sfr->IICxCON1 = BIT(11) | BIT(10) | BIT(5) | BIT(4) | BIT(3) | len;
u32 ticks;
ctp_iic_write_update_kick(dev_addr, addr, cmd, len);
ticks = tick_get();
while (!(CTP_IIC->sfr->IICxCON0 & BIT(31))) {
if (tick_check_expire(ticks, 20)) {
// printf("WRITE UPDATE IIC TOUT\n");
return false;
}
WDT_CLR();
}
CTP_IIC->sfr->IICxCON0 |= BIT(29); //Clear Pending
// delay_5ms(2);
return true;
}
//升级读KICK
void ctp_iic_update_readkick(u8 dev_addr, void *buf, int len)
{
CTP_IIC->sfr->IICxCMDA = (I2C_READ_ADDR(dev_addr)) << 24;
CTP_IIC->sfr->IICxDMAADR = DMA_ADR(buf);
CTP_IIC->sfr->IICxDMACNT = ((len - 1) << 16) | BIT(0);
CTP_IIC->sfr->IICxCON0 |= BIT(28); //KICK
}
//升级读
bool ctp_iic_update_read(u8 dev_addr, void *rbuf, int rlen, u16 w_addr, u8 *w_cmd, int wlen)
{
ctp_iic_update_write(dev_addr, w_addr, w_cmd, wlen);
CTP_IIC->sfr->IICxCON1 = BIT(12) | BIT(11) | BIT(9) | BIT(8) | BIT(7) | rlen;
u32 ticks;
ctp_iic_update_readkick(dev_addr, rbuf, rlen);
ticks = tick_get();
while (!(CTP_IIC->sfr->IICxCON0 & BIT(31))) {
if (tick_check_expire(ticks, 20)) {
// printf("READ UPDATE IIC TOUT\n");
return false;
}
}
CTP_IIC->sfr->IICxCON0 |= BIT(29); //Clear Pending
delay_ms(2);
return true;
}