培训-屏幕、TP驱动相关
📎 原始文档:https://www.kdocs.cn/l/cn29hOq7FTzO 培训-屏幕、TP驱动相关
LCD相关
穿戴类屏幕相关驱动包含SPI、8bit RGB、 8 bit MCU接口屏幕,我们主要使用到的屏幕是SPI接口 ,其中SPI接口又分为单线SPI 、DSP 、QSPI等接口。但是驱动屏幕的操作在701(br28)系列上
屏幕驱动差异
707系列:
使用DBI进行管理,不直接使用spi 或者rgb接口推送屏幕。
DBI 相关配置项

701系列:
使用IMD硬件模块进行管理推屏
IMD相关配置项
695 系列:
直接使用spi进行屏幕推屏驱动和操作
spi 硬件驱动示例
#include "system/includes.h"
#include "media/includes.h"
#include "asm/spi.h"
#include "generic/log.h"
/*
[[[ README ]]]
1. 本spi测试demo提供了spi.c的API使用例程,测试方式为两个spi的环回测试。
spi1设置为主机模式,spi2设置为从机模式,spi1发送数据到spi2,然后接收spi2
原样返回的数据,然后比较发送出去的数据与接收的数据是否一致,一致则说明
验证通过。
2. 本demo涉及BYTE收发测试及DMA收发测试,通过宏SPI_TEST_MODE选择。另外
demo还涉及到spi中断中调用可用于中断的spi API的使用。
3. spi.c的API不包含CS引脚,CS由API以外控制。
4. 请在board_xxx.c中定义配置结构体,例如用到spi1,需要定义spi1_p_data,
否则编译出错。
5. spi的DMA地址需要4字节对齐。
6. 虽然spi.c的API带有spi0,但在有挂spi flash的芯片上使用可能会出问题,
避免使用spi0。
*/
#define SPI1_CS_OUT() \
do { \
JL_PORTB->DIR &= ~BIT(4); \
JL_PORTB->DIE |= BIT(4); \
JL_PORTB->PU &= ~BIT(4); \
JL_PORTB->PD &= ~BIT(4); \
} while(0)
#define SPI1_CS_L() (JL_PORTB->OUT &= ~BIT(4))
#define SPI1_CS_H() (JL_PORTB->OUT |= BIT(4))
#define SPI2_CS_IN() \
do { \
JL_PORTA->DIR |= BIT(3); \
JL_PORTA->DIE |= BIT(3); \
JL_PORTA->PU &= ~BIT(3); \
JL_PORTA->PD &= ~BIT(3); \
} while (0)
#define SPI2_READ_CS() (JL_PORTA->IN & BIT(3))
static u8 slave_dir = 1;
static u8 spi1_send_buf[100] __attribute__((aligned(4)));
static u8 spi1_recv_buf[100] __attribute__((aligned(4)));
static u8 spi2_send_buf[100] __attribute__((aligned(4)));
static u8 spi2_recv_buf[100] __attribute__((aligned(4)));
static spi_dev spi1_hdl = 1;
static spi_dev spi2_hdl = 2;
#define SPI_TEST_BYTE_MODE 0x01
#define SPI_TEST_DMA_MODE 0x02
//测试模式选择
#define SPI_TEST_MODE SPI_TEST_BYTE_MODE
static void my_put_u8hex(u8 b)
{
u8 dat;
dat = b / 16;
if (dat >= 0 && dat <= 9) {
putchar('0' + dat);
} else {
putchar('A' + dat - 10);
}
dat = b % 16;
if (dat >= 0 && dat <= 9) {
putchar('0' + dat);
} else {
putchar('A' + dat - 10);
}
putchar(' ');
}
//中断函数,需以下特殊声明
__attribute__((interrupt("")))
static void spi2_isr()
{
static int i = 0;
if (spi_get_pending(spi2_hdl)) {
spi_clear_pending(spi2_hdl);
if (SPI2_READ_CS()) {
return;
}
#if SPI_TEST_MODE == SPI_TEST_BYTE_MODE
if (slave_dir == 1) {
spi2_recv_buf[i] = spi_recv_byte_for_isr(spi2_hdl);
spi_send_byte_for_isr(spi2_hdl, spi2_recv_buf[i]);
i >= 100 ? i = 0 : i++;
slave_dir = 0;
} else {
slave_dir = 1;
}
#elif SPI_TEST_MODE == SPI_TEST_DMA_MODE
if (slave_dir == 1) {
spi_dma_set_addr_for_isr(spi2_hdl, spi2_recv_buf, 100, 0);
slave_dir = 0;
} else {
slave_dir = 1;
}
#endif
}
}
#if 1 //仅用于spi demo,正式工程请放到board_xxx.c文件中
const struct spi_platform_data spi1_p_data = {
.port = {
IO_PORTB_06, //CLK
IO_PORTB_07, //DO
IO_PORTB_05, //DI
},
.mode = SPI_MODE_BIDIR_1BIT,
.clk = 1000000,
.role = SPI_ROLE_MASTER,
};
const struct spi_platform_data spi2_p_data = {
.port = {
IO_PORTB_02, //CLK
IO_PORTB_03, //DO
IO_PORTB_01, //DI
},
.mode = SPI_MODE_BIDIR_1BIT,
.clk = 1000000,
.role = SPI_ROLE_SLAVE,
};
#endif
void spi_test_main()
{
int i;
int err;
spi_open(spi1_hdl);
spi_open(spi2_hdl);
spi_set_ie(spi2_hdl, 1);
//配置中断优先级,中断函数
request_irq(IRQ_SPI2_IDX, 3, spi2_isr, 0);
SPI1_CS_OUT();
SPI2_CS_IN();
SPI1_CS_H();
for (i = 0; i < 100; i++) {
spi1_send_buf[i] = i % 26 + 'A';
spi1_recv_buf[i] = 0;
}
puts(">>> spi test start\n");
#if SPI_TEST_MODE == SPI_TEST_BYTE_MODE
SPI1_CS_L();
for (i = 0; i < 100; i++) {
err = spi_send_byte(spi1_hdl, spi1_send_buf[i]);
if (err) {
puts("spi1 byte send timeout\n");
break;
}
delay(100);
spi1_recv_buf[i] = spi_recv_byte(spi1_hdl, &err);
if (err) {
puts("spi1 byte recv timeout\n");
break;
}
delay(100);
}
SPI1_CS_H();
#elif SPI_TEST_MODE == SPI_TEST_DMA_MODE
spi_dma_set_addr_for_isr(spi2_hdl, spi2_recv_buf, 100, 1);
SPI1_CS_L();
err = spi_dma_send(spi1_hdl, spi1_send_buf, 100);
if (err < 0) {
puts("spi1 dma send timeout\n");
goto __out_dma;
}
//delay(100);
err = spi_dma_recv(spi1_hdl, spi1_recv_buf, 100);
if (err < 0) {
puts("spi1 dma recv timeout\n");
goto __out_dma;
}
//delay(100);
__out_dma:
SPI1_CS_H();
#endif
puts("<<< spi test end\n");
puts("\nspi master receivce buffer:\n");
for (i = 0; i < 100; i++) {
//my_put_u8hex(spi1_recv_buf[i]);
putchar(spi1_recv_buf[i]), putchar(0x20);
if (i % 16 == 15) {
putchar('\n');
}
}
if (i % 16) {
putchar('\n');
}
if (!memcmp(spi1_send_buf, spi1_recv_buf, 100)) {
puts("\nspi test pass\n");
} else {
puts("\nspi test fail\n");
}
spi_close(spi1_hdl);
spi_close(spi2_hdl);
}
SPI 接口屏幕
spi 接口屏幕也是有不同的时序的,例如普通spi 屏幕就有3-wire spi /4-wire spi
例如 3-wire spi 时序如下 :
4-wire spi
通过上序时序可以, 4-wire spi 会比 3-wire spi 时序上多出一个DCX io口 ,在很多屏幕上也有别名是A0 或者RS脚。csx 主要作用是用于区分数据或者命令 。另外由于4-wire spi 多了一个IO口控制是命令或者数据,所以只需要8bit 数据即可表达RGB数据,而3-wire spi 需要 9bit 数据,用1bit 表示数据或者命令
屏幕驱动流程
以701 为例: cpu\br28\ui_driver\lcd_drive\lcd_drive.c
通过上面截图 lcd_drv_get_hal 获取不同屏幕驱动的指针,指针指向结构体如下:
初始化成功后,可以通过
void lcd_set_draw_area(int xstart, int xend, int ystart, int yend);接口进行绘制。
屏幕切线处理
基础情况屏幕产生撕裂的主要原因是追赶的问题,屏幕读数据和写入屏幕数据速度由于速度不一样,所以出现了撕裂的情况
出现上述情况基本可能存在很多条切,或者单条切线,但是切线位置不固定
当然另外存在一种情况是切线位置固定,这个时候我们就可以通过调整屏幕 0x44 寄存器,或者个别屏幕0xc4寄存器中的te delay
TP 相关
tp工作流程:
初始化 IIC -> 读取设备ID ->检测固件是否需要升级->正常通过TP中断回调读取IIC数据 ->处理IIC 读取数据转换成单击、多击等事件->将事件和坐标信息psot 到ui task
#include "app_config.h"
#include "system/includes.h"
#include "asm/iic_hw.h"
#include "asm/iic_soft.h"
#include "asm/gpio.h"
#include "asm/mcpwm.h"
#include "bl6133.h"
#if TCFG_TOUCH_PANEL_ENABLE
#if TCFG_TP_BL6133_ENABLE
#define SLAVE_DEV_ADDR (0x2C<<1) //固有,不可配置,用于 chipID 读取,固件烧录操作
#ifndef abs
#define abs(x) ((x)>0?(x):-(x) )
#endif
/*************Betterlife ic debug***********/
/* #define LOG_TAG_CONST BL6133 */
#define LOG_TAG "[bl6133]"
#include "debug.h"
#if defined(BL_DEBUG)
/* #define bl_log_trace log_info */
#endif
void delay(volatile u32 t);
void udelay(u32 us);
#define MDELAY(n) mdelay(n)
#undef log_info
#define log_info(fmt, ...)
#include "ui/ui.h"
#include "ui/ui_api.h"
/*************Betterlife ic iic select***********/
#if TCFG_BL6133_USER_IIC_TYPE
#define iic_init(iic) hw_iic_init(iic)
#define iic_uninit(iic) hw_iic_uninit(iic)
#define iic_start(iic) hw_iic_start(iic)
#define iic_stop(iic) hw_iic_stop(iic)
#define iic_tx_byte(iic, byte) hw_iic_tx_byte(iic, byte)
#define iic_rx_byte(iic, ack) hw_iic_rx_byte(iic, ack)
#define iic_read_buf(iic, buf, len) hw_iic_read_buf(iic, buf, len)
#define iic_write_buf(iic, buf, len) hw_iic_write_buf(iic, buf, len)
#define iic_suspend(iic) hw_iic_suspend(iic)
#define iic_resume(iic) hw_iic_resume(iic)
#else
#define iic_init(iic) soft_iic_init(iic)
#define iic_uninit(iic) soft_iic_uninit(iic)
#define iic_start(iic) soft_iic_start(iic)
#define iic_stop(iic) soft_iic_stop(iic)
#define iic_tx_byte(iic, byte) soft_iic_tx_byte(iic, byte)
#define iic_rx_byte(iic, ack) soft_iic_rx_byte(iic, ack)
#define iic_read_buf(iic, buf, len) soft_iic_read_buf(iic, buf, len)
#define iic_write_buf(iic, buf, len) soft_iic_write_buf(iic, buf, len)
#define iic_suspend(iic) soft_iic_suspend(iic)
#define iic_resume(iic) soft_iic_resume(iic)
#endif
static u8 tp_last_staus = ELM_EVENT_TOUCH_UP;
static int tp_down_cnt = 0;
static int tp_int_io_init = 0;
/****************************************************/
bl6133_param bl6133_iic_info_test = {
.iic_hdl = 0,
.iic_delay = 1,
};
/*************************************
*注意:
* bl6133触摸屏iic时钟频率必须小于200k
* **********************************/
static bl6133_param *bl6133_iic_info;
//return =len:ok; other:fail
u16 CTP_FLASH_I2C_WRITE(u8 slave_addr, u8 *buf, u16 len)
{
u16 i = 0;
iic_start(bl6133_iic_info->iic_hdl);
if (0 == iic_tx_byte(bl6133_iic_info->iic_hdl, slave_addr)) {
iic_stop(bl6133_iic_info->iic_hdl);
return 0;
}
for (i = 0; i < len; i++) {
delay(bl6133_iic_info->iic_delay);
if (0 == iic_tx_byte(bl6133_iic_info->iic_hdl, buf[i])) {
iic_stop(bl6133_iic_info->iic_hdl);
return i;
}
}
iic_stop(bl6133_iic_info->iic_hdl);
return i;
}
//return =len:ok; other:fail
u16 CTP_FLASH_I2C_READ(u8 slave_addr, u8 *buf, u16 len)
{
u16 i = 0;
iic_start(bl6133_iic_info->iic_hdl);
if (0 == iic_tx_byte(bl6133_iic_info->iic_hdl, slave_addr + 1)) {
iic_stop(bl6133_iic_info->iic_hdl);
return 0;
}
for (i = 0; i < len - 1; i++) {
delay(bl6133_iic_info->iic_delay);
*buf++ = iic_rx_byte(bl6133_iic_info->iic_hdl, 1);
}
i++;
*buf = iic_rx_byte(bl6133_iic_info->iic_hdl, 0);
iic_stop(bl6133_iic_info->iic_hdl);
return i;
}
void ctp_delay_us(unsigned int time)
{
udelay(time);
}
void ctp_delay_ms(unsigned short time)
{
mdelay(time);
}
void bl_ts_set_intmode(char mode)
{
if (0 == mode) {
//GPIO mode
CTP_SET_I2C_EINT_OUTPUT;
} else if (1 == mode) {
//INT mode
CTP_SET_I2C_EINT_INPUT;
}
}
void bl_ts_set_intup(char level)
{
if (level == 1) {
CTP_SET_I2C_EINT_HIGH;
} else if (level == 0) {
CTP_SET_I2C_EINT_LOW;
}
}
#ifdef INT_PIN_WAKEUP
void bl_ts_int_wakeup(void)
{
bl_ts_set_intmode(0);
bl_ts_set_intup(1);
ctp_delay_ms(20);
bl_ts_set_intup(0);
ctp_delay_ms(1);
bl_ts_set_intup(1);
ctp_delay_ms(20);
bl_ts_set_intmode(1);
}
#endif
#ifdef RESET_PIN_WAKEUP
void bl_ts_reset_wakeup(void)
{
// CTP_SET_RESET_PIN_OUTPUT;
CTP_SET_RESET_PIN_LOW;
ctp_delay_ms(1);
CTP_SET_RESET_PIN_HIGH;
ctp_delay_ms(20);
CTP_SET_RESET_PIN_LOW;
ctp_delay_ms(20);
CTP_SET_RESET_PIN_HIGH;
gpio_set_hd0(CTP_RESET_PIN, 0);
// ctp_delay_ms(20);
}
void bl_ts_reset(void)
{
// CTP_SET_RESET_PIN_OUTPUT;
CTP_SET_RESET_PIN_LOW;
ctp_delay_ms(10);
CTP_SET_RESET_PIN_HIGH;
ctp_delay_ms(100);
gpio_set_hd0(CTP_RESET_PIN, 0);
}
#endif
int Check_bl6133_id(unsigned char *buf)
{
int ret = 0x00;
for (uint8_t t = 0; t < 3; t++) {
bl_ts_reset();
bl_ts_set_intup(0);
ctp_delay_ms(50);
uint8_t sendata[] = {0x0a, 0xf5, 0xe7, 0xe8};
ret = CTP_FLASH_I2C_WRITE(SLAVE_DEV_ADDR, sendata, 4);
if (ret != 4) {
log_error("bl_get_chip_id:i2c write flash error___\n");
ret = -1;
}
ret = CTP_FLASH_I2C_READ(SLAVE_DEV_ADDR, buf, 1);
if (ret != 1) {
log_error("bl_get_chip_id:i2c read flash error___\n");
ret = -1;
}
if (*buf == 0x22) {
bl_ts_reset_wakeup();
log_info("TP_BL6133_CHIP_ID = 0x%02x, check: Pass\r\n", *buf);
return 0;
}
ctp_delay_ms(20);
}
return ret;
}
unsigned char ctp_bl_ts_init(void)
{
uint32_t s;
#ifdef BTL_CHECK_CHIPID
unsigned char chipID = 0x00;
#endif
char ret = 0;
#ifdef RESET_PIN_WAKEUP
#ifndef BTL_CHECK_CHIPID // 读id里面有reset
//bl_ts_reset_wakeup();
bl_ts_reset();
#endif /* #ifndef BTL_CHECK_CHIPID */
#endif
/* #ifdef INT_PIN_WAKEUP */
/* bl_ts_int_wakeup(); */
/* #endif */
MDELAY(20);
#ifdef BTL_CHECK_CHIPID
bl_ts_set_intmode(0);
bl_ts_set_intup(0);
//ret = bl_get_chip_id(&chipID);
ret = Check_bl6133_id(&chipID);
bl_ts_set_intup(1);
bl_ts_set_intmode(1);
if (ret < 0) {
log_error("I2C communication ERROR!");
return false;
} else if (chipID != BTL_FLASH_ID) {
log_error("Please specify the IC model:0x%x!", chipID);
return false;
} else {
log_info("I2C communication success:chipID = %x!", chipID);
}
MDELAY(10);
#endif
#ifdef BL_AUTO_UPDATE_FARMWARE
extern int bl_auto_update_fw(void);
// s = os_lock();////////
wdt_disable();
bl_ts_set_intmode(0);
bl_ts_set_intup(0);
bl_auto_update_fw();
ctp_delay_ms(5);
bl_ts_set_intup(1);
bl_ts_set_intmode(1);
wdt_enable();
// os_unlock(s);////////
#endif
return true;
}
//iic scl:<=200KHz
bool ctp_init_bl6133(void *priv)
{
if (priv == NULL) {
log_error("ctp bl6133 priv ERROR!");
return false;
}
bl6133_iic_info = (bl6133_param *)priv;
bool ret = false;
log_info("the iic speed of ctp-bl6133 must be set below 200k(iic<=200k)!");
bl_ts_set_intmode(1);
CTP_SET_RESET_PIN_OUTPUT;
/* iic_init(bl6133_iic_info->iic_hdl); */
ret = ctp_bl_ts_init();
return ret;
}
void ctp_sleep_bl6133(void)
{
unsigned char data = 0;
unsigned char aa = 0, bb = 0;
unsigned char sleepCmd[] = {0xa5, 0x03};
CTP_FLASH_I2C_WRITE(SLAVE_DEV_ADDR, sleepCmd, 1);
CTP_FLASH_I2C_READ(SLAVE_DEV_ADDR, &aa, 1);
MDELAY(10);
bb = CTP_FLASH_I2C_WRITE(SLAVE_DEV_ADDR, sleepCmd, sizeof(sleepCmd));
log_info("ctp_sleep_bl6133 aa=%d,bb=%d", aa, bb);
// MDELAY(100); //和显示屏共用delay耗时
/* #ifdef INT_PIN_WAKEUP */
/* bl_ts_set_intmode(0); */
/* bl_ts_set_intup(1); */
/* #endif */
log_info("ctp_sleep_bl6133");
}
void ctp_wakeup_bl6133(void)
{
#ifdef RESET_PIN_WAKEUP
bl_ts_reset_wakeup();
#endif
/* #ifdef INT_PIN_WAKEUP */
/* bl_ts_int_wakeup(); */
/* #endif */
bl_ts_set_intmode(1);//开io中断
log_info("ctp_wakeup_bl6133");
}
//void ctp_pad_enter_dlps_bl6133(void){
// Pad_Config(ABH_DRV_PIN_NUM_TP_INT, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_LOW);
// Pad_Config(ABH_DRV_PIN_NUM_TP_RST, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_LOW);
//}
//void ctp_pad_exit_dlps_bl6133(void){
// Pad_Config(ABH_DRV_PIN_NUM_TP_INT, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_LOW);
// Pad_Config(ABH_DRV_PIN_NUM_TP_RST, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH);
//}
void ctp_enter_low_power(void)
{
unsigned char data = 0;
unsigned char aa = 0, bb = 0;
unsigned char sleepCmd[] = {0xa5, 0x01};
CTP_FLASH_I2C_WRITE(CTP_SLAVE_ADDR, sleepCmd, 1);
CTP_FLASH_I2C_READ(CTP_SLAVE_ADDR, &aa, 1);
MDELAY(10);
bb = CTP_FLASH_I2C_WRITE(CTP_SLAVE_ADDR, sleepCmd, sizeof(sleepCmd));
log_info("ctp_enter_low_power aa=%d,bb=%d", aa, bb);
// MDELAY(100); //和显示屏共用delay耗时
log_info("ctp_enter_low_power");
}
void ctp_exit_low_power(void)
{
#ifdef RESET_PIN_WAKEUP
bl_ts_reset_wakeup();
#endif
/* #ifdef INT_PIN_WAKEUP */
/* bl_ts_int_wakeup(); */
/* #endif */
log_info("ctp_exit_low_power");
}
int ctp_poweron(void)
{
//poweron
if (TCFG_TP_POWER_IO == NO_CONFIG_PORT) {
return -1;
}
printf("ctp power on\n");
gpio_direction_output(TCFG_TP_POWER_IO, 1);
u32 tp_io_table[2] = {TCFG_TP_RESET_IO, TCFG_TP_INT_IO};
int i;
for (i = 0; i < sizeof(tp_io_table) / sizeof(tp_io_table[0]); i++) {
gpio_set_die(tp_io_table[i], 1);
}
gpio_direction_output(TCFG_TP_RESET_IO, 0);
iic_init(bl6133_iic_info->iic_hdl);
tp_last_staus = ELM_EVENT_TOUCH_UP;
tp_down_cnt = 0;
return 0;
}
int ctp_poweroff(void)
{
//poweroff
if (TCFG_TP_POWER_IO == NO_CONFIG_PORT) {
return -1;
}
printf("ctp power off\n");
power_wakeup_index_enable(1, false);//中断禁止
gpio_direction_output(TCFG_TP_POWER_IO, 0);
u32 tp_io_table[2] = {TCFG_TP_RESET_IO, TCFG_TP_INT_IO};
int i;
for (i = 0; i < sizeof(tp_io_table) / sizeof(tp_io_table[0]); i++) {
gpio_direction_input(tp_io_table[i]);
gpio_set_pull_up(tp_io_table[i], 0);
gpio_set_pull_down(tp_io_table[i], 0);
gpio_set_die(tp_io_table[i], 0);
}
iic_uninit(bl6133_iic_info->iic_hdl);
return 0;
}
void ctp_enter_sleep(void)
{
ctp_sleep_bl6133();
}
void ctp_exit_sleep(void)
{
ctp_wakeup_bl6133();
}
#define ENERGY_XDISTANCE 15
#define ENERGY_YDISTANCE 15
#define ENERGY_TIME 20 //ms
struct touch_kinetic_energy {
int t1;
int x1;
int y1;
int t2;
int x2;
int y2;
};
static struct touch_kinetic_energy tke = {0};
static void tke_start(int x, int y)
{
memcpy(&tke.t2, &tke.t1, sizeof(tke) / 2);
if ((tke.x1 == x) && (tke.y1 == y)) {
tke.t1 = tke.t1;
} else {
tke.t1 = jiffies_msec();
}
tke.x1 = x;
tke.y1 = y;
/* printf("tke start %d, %d, %d\n", tke.t1, tke.x1, tke.y1); */
}
static void tke_stop(int x, int y, struct touch_event *up_t)
{
struct touch_event t = {0};
u8 xdir, ydir;
if (tke.t1 == 0) {
//在这里发送up消息,因为没有惯性,所以直接发送
ui_touch_msg_post(up_t);
return;
}
tke.t1 = tke.t1 - tke.t2;
tke.x1 = tke.x1 - tke.x2;
tke.y1 = tke.y1 - tke.y2;
/* printf("tke end %d, %d, %d\n", tke.t1, tke.x1, tke.y1); */
if ((tke.t1 < ENERGY_TIME) &&
((abs(tke.x1) > ENERGY_XDISTANCE) || abs(tke.y1) > ENERGY_YDISTANCE)) {
//在这里发送up消息,并附上有惯性能量标志
up_t->has_energy = 1;
ui_touch_msg_post(up_t);
if (abs(tke.x1) <= ENERGY_XDISTANCE) {
tke.x1 = 0;
}
if (abs(tke.y1) <= ENERGY_YDISTANCE) {
tke.y1 = 0;
}
xdir = (tke.x1 < 0) ? 1 : 2;
ydir = (tke.y1 < 0) ? 1 : 2;
/* printf("xdir %d, ydir %d\n", xdir, ydir); */
t.event = ELM_EVENT_TOUCH_ENERGY;
t.x = (tke.x1 << 16) | (tke.t1 & 0xffff);
t.y = (tke.y1 << 16) | (ydir << 8) | (xdir & 0xff);
ui_touch_msg_post(&t);
/* printf("tke out %d, %d, %d, %d, %d\n", (t.x & 0xffff), (t.x >> 16), (t.y >> 16), (t.y & 0xff), (t.y >> 8) & 0xff); */
} else {
//在这里发送up消息,因为没有惯性,所以直接发送
ui_touch_msg_post(up_t);
}
memset(&tke, 0, sizeof(tke));
}
struct touch_info {
int y;
int x;
int p;
int id;
int count;
};
#define Y_MIRROR 0
#define X_MIRROR 0
#define VK_Y 454
#define VK_X 454
#define VK_Y_MOVE 100//227
#define VK_X_MOVE 100//227
#define VK_X_Y_DIFF 47
#define X_SINGLE_MOVE 0 //单次滑动距离上限阈值,用于过滤多点触摸时误发L/R_MOVE事件 0 关闭 ;阈值,根据tp实际情况调整
#define Y_SINGLE_MOVE 0 //y方向过滤
/* struct touch_event { */
/* int event; */
/* int x; */
/* int y; */
/* }; */
#define abs(x) ((x)>0?(x):-(x) )
static void tpd_down(int raw_x, int raw_y, int x, int y, int p)
{
struct touch_event t = {0};
static int first_x = 0;
static int first_y = 0;
#if (X_SINGLE_MOVE && Y_SINGLE_MOVE)
static s16 last_x = 0;
static s16 last_y = 0;
static s16 dist_x = 0;
static s16 dist_y = 0;
#endif
static u8 move_flag = 0;
if (x < 0) {
x = 0;
}
if (x > (VK_X - 1)) {
x = VK_X - 1;
}
if (y < 0) {
y = 0;
}
if (y > (VK_Y - 1)) {
y = VK_Y - 1;
}
#if Y_MIRROR
x = VK_X - x - 1;
#endif
#if X_MIRROR
y = VK_Y - y - 1;
#endif
if ((tp_last_staus == ELM_EVENT_TOUCH_DOWN) && (x == first_x) && (y == first_y)) {
tp_down_cnt++;
if (tp_down_cnt < 30) {
return;
}
tp_last_staus = ELM_EVENT_TOUCH_HOLD;
tp_down_cnt = 0;
t.event = tp_last_staus;
t.x = x;
t.y = y;
log_info("----tpd_hold----");
ui_touch_msg_post(&t);
return;
}
/* log_info("D[%4d %4d %4d]\n", x, y, p); */
//log_info("tp_last_status:%d mf:%d x(%d->%d=%d:%d:%d),y(%d->%d=%d:%d:%d)",tp_last_staus,move_flag,first_x,x,x - first_x,last_x,dist_x,first_y,y,y-first_y,last_y,dist_y);
if (tp_last_staus != ELM_EVENT_TOUCH_UP) {
int x_move = abs(x - first_x);
int y_move = abs(y - first_y);
#if (X_SINGLE_MOVE && Y_SINGLE_MOVE)
int x_last_move = (x - last_x);
int y_last_move = (y - last_y);
if (!move_flag && (abs(dist_x) >= VK_X_MOVE || abs(dist_y) >= VK_Y_MOVE) && (abs(abs(dist_x) - abs(dist_y)) >= VK_X_Y_DIFF)) {
if (abs(dist_x) > abs(dist_y)) {
if (dist_x > 0) {
tp_last_staus = ELM_EVENT_TOUCH_R_MOVE;
log_info("----tpd_rigth_move----");
} else {
tp_last_staus = ELM_EVENT_TOUCH_L_MOVE;
log_info("----tpd_left_move----");
}
} else {
if (dist_y > 0) {
tp_last_staus = ELM_EVENT_TOUCH_D_MOVE;
log_info("----tpd_down_move----");
} else {
tp_last_staus = ELM_EVENT_TOUCH_U_MOVE;
log_info("----tpd_up_move----");
}
}
last_x = x;
last_y = y;
dist_x += x_last_move;
dist_y += y_last_move;
move_flag = 1;
#else
if (!move_flag && (x_move >= VK_X_MOVE || y_move >= VK_Y_MOVE) && (abs(x_move - y_move) >= VK_X_Y_DIFF)) {
if (x_move > y_move) {
if (x > first_x) {
tp_last_staus = ELM_EVENT_TOUCH_R_MOVE;
log_info("----tpd_rigth_move----");
} else {
tp_last_staus = ELM_EVENT_TOUCH_L_MOVE;
log_info("----tpd_left_move----");
}
} else {
if (y > first_y) {
tp_last_staus = ELM_EVENT_TOUCH_D_MOVE;
log_info("----tpd_down_move----");
} else {
tp_last_staus = ELM_EVENT_TOUCH_U_MOVE;
log_info("----tpd_up_move----");
}
}
move_flag = 1;
#endif
} else {
if ((x == first_x) && (y == first_y)) {
return;
}
#if (X_SINGLE_MOVE && Y_SINGLE_MOVE)
if ((abs(x_last_move) > X_SINGLE_MOVE) || (abs(y_last_move) > Y_SINGLE_MOVE)) {
return;
}
last_x = x;
last_y = y;
dist_x += x_last_move;
dist_y += y_last_move;
#endif
tp_last_staus = ELM_EVENT_TOUCH_MOVE;
log_info("----tpd_move----");
}
/* tp_last_staus = ELM_EVENT_TOUCH_HOLD; */
tke_start(x, y);
} else {
#if (X_SINGLE_MOVE && Y_SINGLE_MOVE)
if (tp_last_staus != ELM_EVENT_TOUCH_UP) {
return;
}
tp_last_staus = ELM_EVENT_TOUCH_DOWN;
first_x = x;
first_y = y;
last_x = x;
last_y = y;
dist_x = 0;
dist_y = 0;
#else
tp_last_staus = ELM_EVENT_TOUCH_DOWN;
first_x = x;
first_y = y;
#endif
move_flag = 0;
log_info("----tpd_down----");
}
t.event = tp_last_staus;
t.x = x;
t.y = y;
ui_touch_msg_post(&t);
}
static void tpd_up(int raw_x, int raw_y, int x, int y, int p)
{
struct touch_event t = {0};
if (x < 0) {
x = 0;
}
if (x > (VK_X - 1)) {
x = VK_X - 1;
}
if (y < 0) {
y = 0;
}
if (y > (VK_Y - 1)) {
y = VK_Y - 1;
}
#if Y_MIRROR
x = VK_X - x - 1;
#endif
#if X_MIRROR
y = VK_Y - y - 1;
#endif
/* log_info("U[%4d %4d %4d]\n", x, y, 0); */
tp_last_staus = ELM_EVENT_TOUCH_UP;
tp_down_cnt = 0;
t.event = tp_last_staus;
t.x = x;
t.y = y;
log_info("----tpd_up----");
//不在这里发送up消息,在tke_stop里面!!!
/* ui_touch_msg_post(&t); */
tke_stop(x, y, &t);
}
u8 get_ctp_bl6133_info(struct touch_info *cinfo)
{
static uint8_t keep_times = 0;
uint8_t lvalue[2 + MAX_POINT_NUM * 6];
uint16_t pdwSampleX, pdwSampleY;
unsigned char cmdPoint = 0x01;
CTP_FLASH_I2C_WRITE(SLAVE_DEV_ADDR, &cmdPoint, sizeof(cmdPoint));
CTP_FLASH_I2C_READ(SLAVE_DEV_ADDR, lvalue, sizeof(lvalue));
pdwSampleX = (((unsigned short)(lvalue[2] & 0x0f)) << 8) | lvalue[3];
pdwSampleY = (((unsigned short)(lvalue[4] & 0x0f)) << 8) | lvalue[5];
//BI6133_evt_handle(((lvalue[2]&0xc0)>>6),lvalue[0],pdwSampleX,pdwSampleY);
uint8_t status;
u8 touchAction = 0;
status = ((lvalue[2] & 0xc0) >> 6);
/* log_info("coordinate move:%d statu:%d , x=%d, y=%d",lvalue[0],status, pdwSampleX, pdwSampleY); */
cinfo->p = status; //event flag
cinfo->x = pdwSampleX;
cinfo->y = pdwSampleY;
// if (status == 1) { // Touched
/* if (status == 0 || status == 2) { // Touched */
/* if (gTouched) */
/* touchAction = CD_TOUCH_MOVE; */
/* else */
/* touchAction = CD_TOUCH_DOWN; */
/* gTouched = true; */
/* } else { // Not touched */
/* if (gTouched) */
/* touchAction = CD_TOUCH_UP; */
/* else */
/* touchAction = CD_TOUCH_NONE; */
/* gTouched = false; */
/* } */
/* if (touchAction != CD_TOUCH_NONE) { */
/* //log_info("touchAction=%d", touchAction); */
/* } */
return true;
}
static bool touch_flag = 0;
static bool touch_event_polling_flag = 0; //bl6133不支持
bool BL6133_ID_G_MODE = 1; //bl6133不支持
static int touch_event_handler();
#ifdef CONFIG_CPU_BR23
static int touch_int_handler()
{
touch_flag = 1;
if (BL6133_ID_G_MODE) {
touch_event_handler();
} else {
touch_event_polling_flag = 1;
}
return 0;
}
#elif defined(CONFIG_CPU_BR28)||defined(CONFIG_CPU_BR27)
static void touch_int_handler(u8 index, u8 gpio)
{
if (gpio != CTP_EINT_PIN) {
return ;
}
touch_flag = 1;
if (BL6133_ID_G_MODE) {
touch_event_handler();
} else {
touch_event_polling_flag = 1;
}
}
#endif
static int touch_event_handler()
{
struct touch_info cinfo;
int i = 0;
int last_ms = 0 ;
if (!touch_flag) {
return 0;
}
if(jiffies_msec() - last_ms < 20){
printf("usr return tp msg !!!\n");
return 0;
}
touch_flag = 0;
if (get_ctp_bl6133_info(&cinfo)) {
if (cinfo.p == 0 || cinfo.p == 2) {
tpd_down(cinfo.x, cinfo.y, cinfo.x, cinfo.y, 0);
} else {
tpd_up(cinfo.x, cinfo.y, cinfo.x, cinfo.y, 0);
}
last_ms = jiffies_msec();
//fun test
log_info("coordinate move: statu: , x=%d, y=%d", cinfo.x, cinfo.y);
/* if(cinfo.x>400){ */
/* ctp_enter_low_power(); */
/* }else if(cinfo.x<50){ */
/* ctp_exit_low_power(); */
/* } */
/* if(cinfo.y>400){ */
/* ctp_sleep_bl6133(); */
/* }else if(cinfo.y<50){ */
/* ctp_wakeup_bl6133(); */
/* } */
}
return 0;
}
/* void touch_event_polling() */
/* { */
/* if(touch_event_polling_flag){ */
/* touch_flag = 1; */
/* touch_event_handler(); */
/* if(BL6133_INT_R()==1){ */
/* touch_event_polling_flag=0; */
/* } */
/* } */
/* } */
/* int BL6133_id_g_mode(u8 mode)//1:trigger, 0:polling */
/* { */
/* u8 data_w[2]={FTS_REG_ID_G_MODE,mode}; */
/* int res =0; */
/* res=tpd_i2c_write(data_w, 2); */
/* if(res!=2){ */
/* log_error("set id_g_mode fail!"); */
/* } */
/* return res; */
/* } */
void ui_set_touch_event(void (*touch_event)(void *priv), int interval);
extern void port_wkup_interrupt_init(u32 port, u8 trigger_edge, void (*cbfun)(void));
void bl6133_int_en()
{
/* log_info("-------------------port wkup isr---------------------------"); */
#ifdef CONFIG_CPU_BR23
io_ext_interrupt_init(CTP_EINT_PIN, 1, touch_int_handler);
#elif defined(CONFIG_CPU_BR28)
// br28外部中断回调函数,按照现在的外部中断注册方式
// io配置在板级,定义在板级头文件,这里只是注册回调函数
if (tp_int_io_init == 0) {
port_edge_wkup_set_callback_by_index(1, touch_int_handler); // 序号需要和板级配置中的wk_param对应上
tp_int_io_init = 1;
} else {
power_wakeup_index_enable(1, true);//中断使能
}
#elif defined(CONFIG_CPU_BR27)
port_edge_wkup_set_callback(touch_int_handler);
#endif
/* if (BL6133_ID_G_MODE == 0) { */
/* //定时执行touch_event_polling(); */
/* sys_timer_add((void *)NULL, touch_event_polling, 20); //注册按键扫描定时器 */
/* } */
/* sys_timer_add((void *)NULL, touch_event_handler, 20); //注册按键扫描定时器 */
#if TCFG_UI_ENABLE
ui_set_touch_event(NULL, 0);
#endif
}
void bl6133_test()
{
iic_init(bl6133_iic_info_test.iic_hdl);
if (ctp_init_bl6133(&bl6133_iic_info_test) == true) {
/* bl6133_int_en(); */
log_info("bl6133 init ok!");
} else {
log_error("bl6133 init fail!");
}
}
/**************************test**************************/
#if 0
void bl6133_test1()
{
iic_init(bl6133_iic_info_test.iic_hdl);
if (ctp_init_bl6133(&bl6133_iic_info_test) == true) {
log_info("-------------------port wkup isr---------------------------");
bl6133_int_en();
/* port_wkup_enable(IO_PORTA_04, 1, touch_int_handler); //PA08-IO中断,1:下降沿触发,回调函数port_wkup_irq_cbfun_test */
log_info("bl6133 init ok!");
} else {
log_error("bl6133 init fail!");
}
}
#endif
#endif
#endif
