用BPF实现红外解码

linux 4.18 内核开始支持BPF,所以可以用BPF进行红外解码.红外有很多编码方式;每个都写一个内核中的红外解码会有上百个,好在目前内核只支持使用最广泛的红外协议。另外,lirc 后台进程可以解码。解码过程只需要很少的代码量,所以更倾向于使用不经过用户空间和内核空间的切换的轻量级实现。本文解释了如何解码红外,Bpf程序的结构,Bpf 程序如何维持状态。

红外远程控制使用简单的LED发射红外光 。红外光开关 时间的长短,可以认为类似摩斯码。当检测到一段时间的红外光就是一个脉冲。红外光没有检测到的时间就是一个空闲。

红外接收器无论何时检测到了脉冲或空闲,BPF程序就会执行(如果已经挂载了)。这段程序由带有指向上下文的指针的单一函数入口点构成。对红外解码器,上下文是一个unsigned int 值。对一个包过滤器,上下文就是一个包。 在这里,这个整数值的低24位包含了以毫秒为单位的脉冲或者空闲的长度。高8位是事件类型,可以是LIRC_MODE2_PULSE, LIRC_MODE2_SPACE, 或者LIRC_MODE2_TIMEOUT之一。BPF程序的返回值被忽略了。

如何在两个脉冲之间的空闲太长,会造成按键解码的延迟。例如,我们可能想测量最后一个脉冲之后的空闲来判断红外信息真的已经结束。 因为一个空闲是在两个脉冲之间的时间,就不得不等下一个红外信息的脉冲来或者这空闲的值。因此,这里要有一个超时。如果一个空闲比超时值还要长,就作为LIRC_MODE2_TIMEOUT。通常设为125ms。

 BPF程序可以用很多方式来写,但是最容易的方式就是使用clang 编译的平台BPF。这允许使用一种受限制的C来写,这种C不能使用标准C库以及循环,例如:

 static int eq_margin(int duration, int expected, int margin)
    {
	return (duration >= (expected - margin)) 
     	    && (duration <= (expected + margin));
    }

    int bpf_decoder(unsigned int *sample)
    {
	int duration = *sample & LIRC_VALUE_MASK;
	bool pulse = (*sample & LIRC_MODE2_MASK) == LIRC_MODE2_PULSE;

	if (pulse && eq_margin(duration, 300, 100) {
		// seen short pulse of about 300 microseconds
	}
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值