【电子量产工具】2.输入系统

news2024/9/23 21:18:08

文章目录

  • 前言
  • 一、输入系统分析
  • 二、封装输入结构体
  • 三、底层 touchscreen
  • 四、底层 netinput
  • 五、显示管理层
  • 六、测试程序
    • 测试效果
  • 总结

前言

最近看了 电子量产工具 这个项目,本专栏是对该项目的一个总结。

对于输入系统,这里只介绍 触摸屏线程 和 网络线程。


一、输入系统分析

在这里插入图片描述
在大纲的输入管理器下有 三种输入方式:触摸屏线程,网络线程,标准输入线程

为什么要使用多线程呢?
在单线程程序中,如果某个任务需要花费很长时间,会导致整个程序进入阻塞状态,用户体验不佳。使用多线程可以将这类耗时任务放在后台线程中执行,保持前台线程的响应性,提升用户体验,提高并发性和效率。

底层的触摸屏线程,网络线程标,标准输入线程 与 板子直接交互,负责处理数据和逻辑。
输入管理器 向下负责管理各种输入设备,向上提供APP 所需的各种函数,起承上启下作用。

我们需要写出底层代码,由中间层 调用底层代码 供 上层APP直接使用。

二、封装输入结构体

  1. InputDevice 结构体 模块化 输入设备。
    后面会根据 name 寻找目标输入设备。
typedef struct InputDevice {
	char *name;
	int (*GetInputEvent)(PInputEvent ptInputEvent);						//获取输入事件
	int (*DeviceInit)(void);											//输入设备初始化
	int (*DeviceExit)(void);
	struct InputDevice *ptNext;										//指针,用于连接链表
}InputDevice, *PInputDevice;
  1. InputEvent 结构体 模块化 输入事件。
typedef struct InputEvent {
	struct timeval	tTime;											//触发的时间
	int iType;														//触发事件的类型
	int iX;													//对于触摸屏事件的触摸点x值
	int iY;													//触摸屏事件的触摸点y值
	int iPressure;											//触摸屏事件的触摸点压力值
	char str[1024];											//网络输入事件的输入字符串
}InputEvent, *PInputEvent;

三、底层 touchscreen

  1. 实现 InputEvent 结构体。
    在这里插入图片描述
  2. 触摸屏事件 ,需要使用 tslib 库
    tslib 是一个触摸屏的开源库,可以使用它来访问触摸屏设备。
    在这里插入图片描述
    ts_setup 函数用于在 tslib 中 初始化触摸屏设备 并 设置相关参数,包括 打开触摸屏设备、校准触摸屏、配置参数和注册触摸事件回调函数等。

  1. 获取 触摸屏 事件的 输入数据。
    在这里插入图片描述
    ts_read:用于从触摸屏设备中读取触摸事件的数据,并存储到 samp 结构体中。
    struct ts_sample:用于存储获取到的触摸屏输入数据。它通常包含一些字段,表示触摸点的位置、时间戳和其他相关信息。

四、底层 netinput

netinputtouchscreen 一样 都需要实现 InputEvent 结构体,初始化输入设备,获取输入事件数据。

  1. 涉及网络通信,要了解一些基本知识:
  • 网络传输中的2个对象:serverclient
    在这里插入图片描述
  • UDP 网络通信大概交互图:
    在这里插入图片描述
  1. 网络输入初始化。
    AF_INET 是针对 Internet 的通讯协族,可以允许远程通信使用。
    SOCK_DGRAM 表明用的是 UDP 协议
static int NetinputDeviceInit(void)
{
	struct sockaddr_in tSocketServerAddr;
	int iRet;
	
	/* socket 函数创建一个套接字,成功时返回文件描述符 */
	g_iSocketServer = socket(AF_INET, SOCK_DGRAM, 0);				
	if (-1 == g_iSocketServer)
	{
		printf("socket error!\n");
		return -1;
	}

	tSocketServerAddr.sin_family      = AF_INET;
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
 	tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
	memset(tSocketServerAddr.sin_zero, 0, 8);
	
	/* 将地址绑定到一个套接字 */
	iRet = bind(g_iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
	if (-1 == iRet)
	{
		printf("bind error!\n");
		return -1;
	}

	return 0;
}
  1. 接收输入事件。
    recvfrom 通常用于无连接套接字, 可以获得发送者的地址。
    gettimeofday 函数,它是一个 C 标准库中的函数,主要用于获取当前的系统时间
static int NetinputGetInputEvent(PInputEvent ptInputEvent)
{
	struct sockaddr_in tSocketClientAddr;
	int iRecvLen;
	char aRecvBuf[1000];
	
	unsigned int iAddrLen = sizeof(struct sockaddr);
	
	/* 接收数据 */
	iRecvLen = recvfrom(g_iSocketServer, aRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
	if (iRecvLen > 0)
	{
		aRecvBuf[iRecvLen] = '\0';
		//printf("Get Msg From %s : %s\n", inet_ntoa(tSocketClientAddr.sin_addr), ucRecvBuf);
		ptInputEvent->iType 	= INPUT_TYPE_NET;
		gettimeofday(&ptInputEvent->tTime, NULL);			//获取时间
		strncpy(ptInputEvent->str, aRecvBuf, 1000);
		ptInputEvent->str[999] = '\0';
		return 0;
	}
	else
		return -1;
}

五、显示管理层

  1. 将 触摸屏输入 和 网络输入 注册进入链表。头添加的方式,添如链表。
    在这里插入图片描述
  2. 对于环形缓冲区这里就不多说了,不懂的可以参考我之前的文章:环形缓冲区

如果我们频繁快速的持续向计算机输入数据,计算机可能执行某个进程不能及时的执行输入的数据,导致数据丢失。这时,我们可以将要输入的数据放入环形缓冲区内,计算机就不会造成数据丢失。

#define BUFFER_LEN 20							//缓冲区数组长度
static int g_iRead  = 0;						//读指针
static int g_iWrite = 0;						//写指针
static InputEvent g_atInputEvents[BUFFER_LEN];			//缓冲区数组

/* 判断缓冲区是否满 */
static int isInputBufferFull(void)
{
	return (g_iRead == ((g_iWrite + 1) % BUFFER_LEN));
}
/* 判断缓冲区是否空 */
static int isInputBufferEmpty(void)
{
	return (g_iRead == g_iWrite);
}
/* 写入数据进缓冲区 */
static void PutInputEventToBuffer(PInputEvent ptInputEvent)
{
	if (!isInputBufferFull())
	{
		g_atInputEvents[g_iWrite] = *ptInputEvent;
		g_iWrite = (g_iWrite + 1) % BUFFER_LEN;
	}
}
/* 从缓冲区读出数据 */
static int GetInputEventFromBuffer(PInputEvent ptInputEvent)
{
	if (!isInputBufferEmpty())
	{
		*ptInputEvent = g_atInputEvents[g_iRead];
		g_iRead = (g_iRead + 1) % BUFFER_LEN;
		return 1;
	}
	else
	{
		return 0;
	}
}

  1. 初始化设备并创建线程。环形缓冲区有数据则唤醒线程。

这里使用了 互斥锁操作,在调用 pthread_cond_wait 前,必须先获取互斥锁,即使用 pthread_mutex_lock 函数。这确保了在等待条件期间的正确 同步 。

pthread_cond_wait 函数会在等待时自动解锁并将线程置于等待状态。当满足特定条件时,该线程会被唤醒并重新获得锁
使用 pthread_cond_signal 函数来 唤醒 等待线程。

在这里插入图片描述

六、测试程序

  1. 触摸屏输入事件测试。
    只需要在 main 函数里调用 输入管理层的封装好的函数即可。

  2. 网络输入事件测试。
    还需要编写一个 client.c 文件,进行客户端 和 服务端的通信。

int main(int argc, char **argv)
{
	int ret;
	InputEvent event;
	
	InputInit();
	IntpuDeviceInit();

	while (1)
	{
		printf("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
		ret = GetInputEvent(&event);

		printf("%s %s %d, ret = %d\n", __FILE__, __FUNCTION__, __LINE__, ret);
		if (ret) {
			printf("GetInputEvent err!\n");
			return -1;
		}
		else
		{
			printf("%s %s %d, event.iType = %d\n", __FILE__, __FUNCTION__, __LINE__, event.iType );
			if (event.iType == INPUT_TYPE_TOUCH)				//触摸屏事件
			{
				printf("Type      : %d\n", event.iType);
				printf("iX        : %d\n", event.iX);
				printf("iY        : %d\n", event.iY);
				printf("iPressure : %d\n", event.iPressure);
			}
			else if (event.iType == INPUT_TYPE_NET)				//网络输入事件
			{
				printf("Type      : %d\n", event.iType);
				printf("str       : %s\n", event.str);
			}
		}
	}
	return 0;	
}

测试效果

触摸屏事件:
在这里插入图片描述
网络输入事件:
在这里插入图片描述


总结

输入系统 的 触摸屏事件 设计 tslib 库,所以在编译时,一定要链接库。
网络输入事件的 通信 使用 UDP 会比较容易,那些函数 以及 通信流程 要了解。
网络输入事件 包括 客户端服务端 间的通信,要编写 client 文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/713434.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7-WebApis-6

Web APIs - 6 目标:能够利用正则表达式完成小兔鲜注册页面的表单验证,具备常见的表单验证能力 正则表达式综合案例阶段案例 正则表达式 正则表达式(Regular Expression是一种字符串匹配的模式(规则) 使用场景&#…

微信小程序申请

方案说明: 微信小程序申请步骤有两个过程,目前采用的是第二种方案 第一种方案:直接向微信申请微信小程序 第二种方案:先申请公众号后再通过公众号快速注册并申请小程序 无论申请公众号还是小程序都需要微信认证,微…

ubuntu18.04下安装PCL

整体步骤可参考:https://blog.csdn.net/qq_42257666/article/details/124574029 在本人安装过程中,遇到一些问题,做几点说明: 1.在配置VTK的过程中报错如下: 解决方法: sudo apt install libqt5x11extras…

Nginx【Nginx核心指令(rewrite指令、实战rewrite 、if指令、set和break指令】(六)-全面详解(学习总结---从入门到深化)

目录 Nginx核心指令_rewrite指令 Nginx核心指令_实战rewrite Nginx核心指令_if指令 Nginx核心指令_set和break指令 Nginx核心指令_rewrite指令 地址重写与地址转发 地址重写 地址重写是实际上是为了实现址标准化,就像访问www.baidu.cn可 以出现www.baidu.com的…

阿里云企业邮箱标准版用户数功能说明

阿里云企业邮箱标准版不同用户数费用表,标准版企业邮箱不限制账号容量、20GB共享网盘容量、5GB个人网盘容量,默认5个账号数540元一年,原价是600元一年,年付9折、多年付8折,阿里云百科分享企业邮箱标准版不同账号数收费…

软件测试技能,JMeter压力测试教程,请求body自动签名带上sign参数(二十一)

一、前言 接口请求body带有sign签名参数,sign签名是根据请求body除去sign本身参数后,拼接请求参数最后md5加密生成的 使用 jmeter 测试接口,我们希望在请求之前修改 post body 里面的 sign 参数的值为签名的值 二、sign签名 签名一篇的实…

Alibaba Sentinel | 熔断规则详解

文章目录 简介熔断策略-慢调用比例结论:流程图:熔断结果详细解释 熔断策略-异常比例结论:详细解释 熔断策略-异常数结论:详细解释 统计异常数、比例的方法编码加注解RuntimeException 总结 简介 熔断是一种保护机制,用…

Redis持久化(RDB、AOF)

Redis持久化(RDB、AOF) 一、Redis高可用二、Redis持久化三、Redis的RDB持久化1、触发条件1.1 手动触发1.2 自动触发1.3 其它自动触发机制 2、执行流程3、启动时加载RED文件(恢复) 四、Redis的AOF持久化1、开启AOF2、执行流程2.1 命令追加(app…

杂记:逆向一块FPGA核心板

最近太热了,实在无心看书。阵列书丢一边看不进去,还买了几本统计信号的甚至都没开始看(笑),躺在床上玩玩手机摆烂,看到某黄色APP上有老板卖拆机的板子,价格美丽,美中不足的是没有资料…

JavaFX布局详解与代码实例

JavaFX布局详解与代码实例 一、JavaFX布局的原理1.1 JavaFX布局容器1.2 布局约束 二、常用JavaFX布局2.1 VBox和HBox布局2.2 GridPane布局2.3 BorderPane布局 三、JavaFX布局代码实例四、总结与展望 正文: 引言: JavaFX是一种功能强大的用户界面&#xf…

SFP6012-ASEMI代理MHCHXM(海矽美)二极管SFP6012

编辑:ll SFP6012-ASEMI代理MHCHXM(海矽美)二极管SFP6012 型号:SFP6012 品牌:MHCHXM(海矽美) 封装:TO-247AB 恢复时间:≤75ns 正向电流:30A 反向耐压&a…

Excel表格转换

原始数据 1部 2部 3部 4部 5部 6部 7部 8部 9部 郈思 王瑾 郈思 许嘉 郈思 施眉 郈思 王瑾 郈思 许嘉 郈思 许嘉 吕倩倩 孙帮菊 夏侯瑾 孙帮菊 吕倩倩 孙痴梦 孙帮菊 姜佳 王瑾 孙痴梦 王瑾 许嘉 施眉 施眉 杨婕 施眉 施眉 孙帮菊 杨孝洁 施眉 吕倩倩 孙痴梦 郈思 夏侯瑾 李文…

NR 吞吐量测试

前言 参考文档: 5G NR TBS (Transport Block size) Calculator | 5G-Tools.com 5G NR Transport Block Size (TBS) Calculation - Techplayon 5G MCS _ 搜索结果_哔哩哔哩_Bilibili 4/5G无线资源和数据调度流程:CQI上报、基站AMC调度、调度信息DCI下发、CQI到MCS的对…

网络控制地址转换管理技术

网络控制&地址转换&管理技术 一、网络控制技术ACL1.1、ACL应用场景1.2、ACL分类1.3、ACL规则1.4、基本ACL配置1.5、高级ACL配置1.6、总结 二、网络地址转换NAT2.1、NAT应用场景2.2、静态NAT2.3、静态NAT配置2.4、动态NAT2.5、动态NAT配置12.6、动态NAT配置22.7、NAPT2.…

【C语言督学训练营 第十六天】考研中常考的排序大题(上)---- 冒泡排序、插入排序、快速排序

文章目录 前言经典的冒泡插入排序快速排序 前言 今天要介绍的部分是排序算法,在很久很久之前学习过十大排序,当时自我感觉非常良好,知道今天才知道我认为的大错特错。有些排序算法会考代码题,有些只会考小题只需要理解思想即可&a…

火山引擎DataLeap数据质量解决方案和最佳实践(二):解决方案

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 DataLeap流批数据质量解决方案 产品功能架构 火山引擎DataLeap流批数据质量解决方案有 4 个大的功能: 离线数据质量监控:解决批和微批监控…

Spring Boot 中的 CD 工具

Spring Boot 中的 CD 工具 在现代软件开发中,持续交付(Continuous Delivery,简称 CD)已经成为了一个非常重要的开发模式。CD 工具可以帮助我们自动化构建、测试、部署和发布软件,提高软件交付的速度和质量。在 Spring…

接口增量改动,研发经常忘通知测试,如何解决?

不知道大家有没有同感,做接口测试麻烦的不是测试本身,而是接口它会变,更麻烦的不是接口变了,而是它变了而你不知道。等到你测完,开发才悠悠跟你说 ——“那个接口我改了点东西,你再看一眼哈”。 我那是看一…

el-menu嵌套路由高亮

1、配置路由 2、一级导航页面配置 计算属性定义方法 3、二级导航页面

mysql知识点总结

MySQL的binlog有有几种录入格式?分别有什么区别? 有三种格式,statement,row和mixed. statement模式下,记录单元为语句.即每一个sql造成的影响会记录.由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制. row级别…