A触摸框协议分析

触摸框串口坐标数据包包的大小基本上都是67 个Byte,但是格式稍有差异。有的6个点,有的10个点,带宽度和不带宽度,某个字节特殊定义等等。

一、串口配置
波特率: 115200
数据位: 8位
停止位: 1 位
奇偶校验: 无

二、触摸框规格
触摸框的分辨率为32767*32767,坐标原点为左上角。当无触摸时,不发送数据,当有触摸时,触摸框通过串口发送一包67 Byte 数据。
三、数据处理
串口工具接触摸框串口,注意接地。将工具中数据拷贝到notepad 或者UE中,通过每67个byte一行,空格隔开。然后处理的文本协议数据拷贝到excel 中,由于一个文本框有67个byte 数据。
A.数据分列
选择单列所有数据,【数据】-【分列】-【设置分隔符号】-【空格】-【完成】,这样单列67个byte 分别分配到67列中。方法链接
B.格式设置
设置数字00 格式显示,保证统一数字宽度
全选后,右键【设置单元格格式】-【数字】-【分类:自定义】-【类型】-【00】

C.表格设置
截取部分头部,尾部和中间一个点的信息,如下
在这里插入图片描述
全部梳理清楚后,通过action前后状态判定事件,触控点个数,x,y 坐标等等,非常方便
四、协议格式
在这里插入图片描述
其中,data【0】,data【1】 是数据包头,
data【2】是数据包字节长度低字节,固定为67(0x43),
data【3】是数据包字节长度高字节,由于总共为67个低位已经满足,这里默认是00
Data【4】是触控点形状,板擦 或 笔
Data【5 ~ 10】第1个点的状态(Action),ID(0),X的位置的高低字节,Y的位置的高低字节
Data【11 ~ 16】第2个点的状态(Action),ID(1),X的位置的高低字节,Y的位置的高低字节
Data【17 ~ 22】第3个点的状态(Action),ID(2),X的位置的高低字节,Y的位置的高低字节
Data【23 ~ 28】第4个点的状态(Action),ID(3),X的位置的高低字节,Y的位置的高低字节
Data【29 ~ 34】第5个点的状态(Action),ID(4),X的位置的高低字节,Y的位置的高低字节
Data【35 ~ 40】第6个点的状态(Action),ID(5),X的位置的高低字节,Y的位置的高低字节
Data【41 ~ 46】第7个点的状态(Action),ID(6),X的位置的高低字节,Y的位置的高低字节
Data【47 ~ 52】第8个点的状态(Action),ID(7),X的位置的高低字节,Y的位置的高低字节
Data【53 ~ 58】第9个点的状态(Action),ID(8),X的位置的高低字节,Y的位置的高低字节
Data【59 ~ 64】第10个点的状态(Action),ID(9),X的位置的高低字节,Y的位置的高低字节

Data【65】有效触摸点的数量,范围是[1 ~ 10],最多支持10指
Data【66】校验和,求data[0 ~ 65]之和,取低字节

部分数据格式如下:

					01						02						03							SUM

index 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 65 66

1F	F7	43	00	00	02	00	38	60	08	1E	02	01	30	65	50	1D	00	02	00	00	00	00	02	4C
1F	F7	43	00	00	03	00	38	60	08	1E	03	01	30	65	40	1D	00	02	00	00	00	00	02	3E
1F	F7	43	00	00	03	00	38	60	08	1E	03	01	30	65	38	1D	00	02	00	00	00	00	02	36
1F	F7	43	00	00	03	00	38	60	08	1E	03	01	30	65	38	1D	00	02	00	00	00	00	02	36
1F	F7	43	00	00	03	00	40	60	08	1E	03	01	48	65	D0	1D	03	02	A0	6E	E0	2D	03	0D
1F	F7	43	00	00	03	00	48	60	08	1E	03	01	48	65	D0	1D	02	02	A0	6E	E0	2D	03	14
1F	F7	43	00	00	03	00	48	60	00	1E	03	01	48	65	D0	1D	00	02	00	00	00	00	02	EE
1F	F7	43	00	00	03	00	48	60	00	1E	03	01	48	65	D0	1D	00	02	00	00	00	00	02	EE
1F	F7	43	00	00	03	00	48	60	00	1E	03	01	48	65	D0	1D	00	02	00	00	00	00	02	EE
1F	F7	43	00	00	03	00	48	60	00	1E	03	01	48	65	D0	1D	00	02	00	00	00	00	02	EE
1F	F7	43	00	00	03	00	48	60	00	1E	03	01	48	65	D0	1D	00	02	00	00	00	00	02	EE
1F	F7	43	00	00	03	00	40	60	00	1E	03	01	48	65	D0	1D	00	02	00	00	00	00	02	E6
1F	F7	43	00	00	03	00	40	60	00	1E	02	01	48	65	D0	1D	00	02	00	00	00	00	02	E5
1F	F7	43	00	00	03	00	48	60	00	1E	00	01	00	00	00	00	00	02	00	00	00	00	01	50
1F	F7	43	00	00	03	00	50	60	00	1E	00	01	00	00	00	00	00	02	00	00	00	00	01	58
1F	F7	43	00	00	02	00	50	60	00	1E	00	01	00	00	00	00	00	02	00	00	00	00	01	57

1.每个点信息起始为:data[i6+5] ; // 其中6表示一个点里面6个byte标记信息,5表示前4个byte 基本为头信息
2.ID 的范围为[0~9],一包数据(67byte)下来,ID 的值都是固定的,从0~9 占用的byte 位为 Byte[6, 12,18,24,30,36,42,48,54,60] = [00,01,02,03,04,05,06,07,08]
3.Byte[65] 为触摸的手指个数,N根手指在屏里面数字就为N,但最后一根手指抬起后,该byte位不会再补发0
4.点的UP,DOWN,MOVE 事件,需要前后两个action状态翻转来判断
// preActionState[0~9], curActionState[0~9] = byte[i
6+5], 前置状态触摸前都为00

5.UP,DOWN,MOVE事件处理之后注意前置状态的重新设置,确保前置和当前状态唯一标识一个UP,DOWN,MOVE,ALL_UP 事件,最终的是要避免多发UP/DOWN
6.每个手指的UP/DOWN 事件必须是一一对应, 不能出现count[UP] != count[DOWN]

状态变换
在这里插入图片描述
在这里插入图片描述
五、触摸事件
上层触摸事件,可以通过USB 触控模拟出来,通过getevent -l 打印出来。

单点的DOWN,UP 事件
在这里插入图片描述

EVENT 分为EV_ABS,EV_KEY,EV_SYN 三种类型
在这里插入图片描述

单点的DOWN,MOVE事件
在这里插入图片描述

串口触摸事件 与 USB口触摸事件的对比
在这里插入图片描述
串口模拟的事件就是协议解析结束之后,需要/dev/uinput发送的事件

六、解析流程图

在这里插入图片描述在这里插入图片描述

七、协议解析源码

void sendEvent(unsigned char tmpBuff[])
{
    int width = 0;
    unsigned char nPosStartIndex = 0;
    unsigned int  unUsefulDotCnt = tmpBuff[VALID_DOT_NUMBER_IN_EACH_PACKGE];
    touchCount   = unUsefulDotCnt;
    for(int i = 0; i < DOTCNT_OF_PACKAGE; i++){
        struct timeval tv;
        gettimeofday(&tv,NULL);

        nPosStartIndex = i * CNT_OF_DOT + 5;
        action = tmpBuff[nPosStartIndex];
        id = tmpBuff[nPosStartIndex + 1];
        
        // record the useful dot count
        if(unUsefulDotCnt != 0x00){
            touchCount = unUsefulDotCnt;
        }

        if(id > TOUCH_COUNT){  // ID < 12
            printf( "\033[1;31;40m  Touch data error,id:%d. \n\033[0m", id);
            continue;//break;
        }

        //  pos (x,y)
        x = tmpBuff[nPosStartIndex+2] + (tmpBuff[nPosStartIndex+3] << 8);
        y = tmpBuff[nPosStartIndex+4] + (tmpBuff[nPosStartIndex+5] << 8);

        if(!isNoWidth){
            // Dot width
            width = tmpBuff[nPosStartIndex + 6] + (tmpBuff[nPosStartIndex + 7] << 8);
        }

        if(action == 0x02){
            // printf("[%s][%d] id[%d] preTouchAct[%d] = [0x%02x] action: [0x%02x] touchCount=[%d] count = [%d] unUsefulDotCnt=[%d] \n",__FUNCTION__,__LINE__, id,id,preTouchAct[id],action,touchCount,count,unUsefulDotCnt);
            if(preTouchAct[id] == 0x03 || preTouchAct[id] == 0x02){
                touchCount--;
                write_event_to_device(EV_ABS, ABS_MT_SLOT, id);
                write_event_to_device(EV_ABS, ABS_MT_TRACKING_ID, -1);
                if(touchCount == 0){
                    write_event_to_device(EV_KEY, BTN_TOUCH, 0);   // UP to Android
                    printf("[%s][%d]...... id = [%d] ALL UP .\n",__FUNCTION__,__LINE__,id);
                }else{
                    printf("[%s][%d]..... id = [%d]. ONE UP .\n",__FUNCTION__,__LINE__,id);  
                }
                write_event_to_device(EV_SYN, SYN_REPORT, 0);
                preTouchAct[id] = 0x00;  // set default when dot up
            }else if(preTouchAct[id] == 0x00){
                printf("[%s][%d]...... id = [%d] DOWN....\n",__FUNCTION__,__LINE__,id);
                count++;
                trackingId[id] = count;
                write_event_to_device(EV_ABS, ABS_MT_SLOT, id);
                write_event_to_device(EV_ABS, ABS_MT_TRACKING_ID, count);
                write_event_to_device(EV_ABS, ABS_MT_POSITION_X, x);
                write_event_to_device(EV_ABS, ABS_MT_POSITION_Y, y);

                if(!isNoWidth){
                    write_event_to_device(EV_ABS, ABS_MT_WIDTH_MAJOR, width);
                }
                write_event_to_device(EV_KEY, BTN_TOUCH, 1);  // DOWN to Android
                write_event_to_device(EV_SYN, SYN_REPORT, 0);
                preTouchAct[id] = action;
            }
        }else if(action == 0x03){
            // printf("[%s][%d] id[%d] preTouchAct[%d] = [0x%02x] action: [0x%02x] touchCount=[%d] count = [%d] unUsefulDotCnt=[%d] \n",__FUNCTION__,__LINE__, id,id,preTouchAct[id],action,touchCount,count,unUsefulDotCnt);
            if(preTouchAct[id] == 0x00){
                printf("[%s][%d]...... id = [%d] EXTRA DOWN....\n",__FUNCTION__,__LINE__,id);
                count++;
                trackingId[id] = count;
                write_event_to_device(EV_ABS, ABS_MT_SLOT, id);
                write_event_to_device(EV_ABS, ABS_MT_TRACKING_ID, count);
                write_event_to_device(EV_ABS, ABS_MT_POSITION_X, x);
                write_event_to_device(EV_ABS, ABS_MT_POSITION_Y, y);

                if(!isNoWidth){
                    write_event_to_device(EV_ABS, ABS_MT_WIDTH_MAJOR, width);
                }
                write_event_to_device(EV_KEY, BTN_TOUCH, 1);
                write_event_to_device(EV_SYN, SYN_REPORT, 0);
                preTouchAct[id] = action;
                //move
                write_event_to_device(EV_ABS, ABS_MT_SLOT, id);
                write_event_to_device(EV_ABS, ABS_MT_TRACKING_ID, trackingId[id]);
                write_event_to_device(EV_ABS, ABS_MT_POSITION_X, x);
                write_event_to_device(EV_ABS, ABS_MT_POSITION_Y, y);
                #if (TOUCH_HAS_WIDTH == 1)
                    write_event_to_device(EV_ABS, ABS_MT_WIDTH_MAJOR, width);
                #endif
                write_event_to_device(EV_SYN, SYN_REPORT, 0);
                tmpX[id] = x;
                tmpY[id] = y;
            }else if((preTouchAct[id] == 0x02)||(abs(tmpX[id] - x) > 17 || abs(tmpY[id] - y) > 30)){//最大坐标除以分辨率,拿到比例
                printf("[%s][%d]...... id = [%d] MOVE....\n",__FUNCTION__,__LINE__,id);
                write_event_to_device(EV_ABS, ABS_MT_SLOT, id);
                write_event_to_device(EV_ABS, ABS_MT_TRACKING_ID, trackingId[id]);
                write_event_to_device(EV_ABS, ABS_MT_POSITION_X, x);
                write_event_to_device(EV_ABS, ABS_MT_POSITION_Y, y);

                if(!isNoWidth){
                    write_event_to_device(EV_ABS, ABS_MT_WIDTH_MAJOR, width);
                }
                write_event_to_device(EV_SYN, SYN_REPORT, 0);
                tmpX[id] = x;
                tmpY[id] = y;
                preTouchAct[id] = action;
            }
        }else if(action == 0x00){
            //
        }
        printf("\n\n\n");
    }
}

代码还有待优化。

八、性能优化(后续)

  1. 代码逻辑优化;
  2. 增加多线程完成事件发送;
  3. 通过内存映射完成事件发送;
发布了101 篇原创文章 · 获赞 19 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/kehyuanyu/article/details/95996289