IR驱动开发¶
概述
红外遥控的发射电路是采用红外发光二极管来发出经过调制的红外光波;红外接收电路由红外接收二极管、 三极管或硅光电池组成,它们将红外发射器发射的红外光转换为相应的电信号,再送后置放大器。鉴于家用电器的品种多样化和用户的使用特点,生产厂家对进行了严格的规范编码,这些编码各不相同,从而形成不同的编码方式,统一称为红外遥控器编码传输协议。到目前为止,红外遥控协议已多达十种, 如: RC5、SIRCS、Sy、RECS80、Denon、NEC、Motorola、Japanese、SAMSWNG 和 Daewoo 等。我国家用电器的红外遥控器的生产厂家,其编码方式多数是按上述的各种协议进行编码的,而用得较多的有 NEC 协议。目前 RK 平台也只支持 NEC 编码的红外协议。
RK 平台上红外实现原理简介
PWM 有三种工作模式, reference mode, one-shot mode 和 continuousmode. 红外遥控器就采用 reference mode,这种模式下 PWM 可以捕获输入高低电平的宽度,并产生中断, CPU接收到中断后去相应的寄存器读取。
按下遥控的时候,红外接收头会产生一系列的高低电平, PWM 就会产生相应的中断, CPU 读取相应的寄存器就知道这些高低电平的时间,根据协议就可以解码出红外的用户码和键值码出来。 下图是 NEC 红外编码协议的简单示意图,详细的协议附在最后。
DTS配置
&pwm3 {
status = "okay";
pinctrl-names = "default";//为IR rx模式,不要配置为gpio模式
interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH 0>;
compatible = "rockchip,remotectl-pwm";
remote_pwm_id = <3>;
handle_cpu_id = <1>;
ir_key1 {
rockchip,usercode = <0x4040>;
rockchip,key_table =
<0xf2 KEY_REPLY>,
<0xba KEY_BACK>,
<0xf4 KEY_UP>,
<0xf1 KEY_DOWN>,
<0xef KEY_LEFT>,
<0xee KEY_RIGHT>,
<0xbd KEY_HOME>,
<0xea KEY_VOLUMEUP>,
<0xe3 KEY_VOLUMEDOWN>,
<0xe2 KEY_SEARCH>,
<0xb2 KEY_POWER>,
<0xbc KEY_MUTE>,
<0xec KEY_MENU>,
<0xbf 0x190>,
<0xe0 0x191>,
<0xe1 0x192>,
<0xe9 183>,
<0xe6 248>,
<0xe8 185>,
<0xe7 186>,
<0xf0 388>,
<0xbe 0x175>;
};
ir_key2 {
rockchip,usercode = <0xff00>;
rockchip,key_table =
<0xf9 KEY_HOME>,
<0xbf KEY_BACK>,
<0xfb KEY_MENU>,
<0xaa KEY_REPLY>,
<0xb9 KEY_UP>,
<0xe9 KEY_DOWN>,
<0xb8 KEY_LEFT>,
<0xea KEY_RIGHT>,
<0xeb KEY_VOLUMEDOWN>,
<0xef KEY_VOLUMEUP>,
<0xf7 KEY_MUTE>,
<0xe7 KEY_POWER>,
<0xfc KEY_POWER>,
<0xa9 KEY_VOLUMEDOWN>,
<0xa8 KEY_VOLUMEDOWN>,
<0xe0 KEY_VOLUMEDOWN>,
<0xa5 KEY_VOLUMEDOWN>,
<0xab 183>,
<0xb7 388>,
<0xe8 388>,
<0xf8 184>,
<0xaf 185>,
<0xed KEY_VOLUMEDOWN>,
<0xee 186>,
<0xb3 KEY_VOLUMEDOWN>,
<0xf1 KEY_VOLUMEDOWN>,
<0xf2 KEY_VOLUMEDOWN>,
<0xf3 KEY_SEARCH>,
<0xb4 KEY_VOLUMEDOWN>,
<0xbe KEY_SEARCH>;
};
ir_key3 {
rockchip,usercode = <0x1dcc>;
rockchip,key_table =
<0xee KEY_REPLY>,
<0xf0 KEY_BACK>,
<0xf8 KEY_UP>,
<0xbb KEY_DOWN>,
<0xef KEY_LEFT>,
<0xed KEY_RIGHT>,
<0xfc KEY_HOME>,
<0xf1 KEY_VOLUMEUP>,
<0xfd KEY_VOLUMEDOWN>,
<0xb7 KEY_SEARCH>,
<0xff KEY_POWER>,
<0xf3 KEY_MUTE>,
<0xbf KEY_MENU>,
<0xf9 0x191>,
<0xf5 0x192>,
<0xb3 388>,
<0xbe KEY_1>,
<0xba KEY_2>,
<0xb2 KEY_3>,
<0xbd KEY_4>,
<0xf9 KEY_5>,
<0xb1 KEY_6>,
<0xfc KEY_7>,
<0xf8 KEY_8>,
<0xb0 KEY_9>,
<0xb6 KEY_0>,
<0xb5 KEY_BACKSPACE>;
};
};
字母和符号键都是 linux 的标准键值,在可以在 include/dt-bindings/input/input.h 中查找。
驱动位置
/kernel/drivers/input/remotectl/rockchip_pwm_remotectl.c
debug
1、打开打印键值的调试开关 echo 1 > sys/module/rockchip_pwm_remotectl/parameters/code_print
按遥控器的按键,记录下对应的键值 例如按向下键,有如下打印 [19634.735833] GET USERCODE=0x4040 [19634.762463] RMC_GETDATA=e9 则,该遥控器的 usercode 是 0x4040,向下键的键值就是 0xe9,如此反复,直到打印完遥控器上的所有键值。
2、有时候需要配合 echo 1 > /sys/module/rockchip_pwm_remotectl/parameters/code_print 一起打印,然后看出错的时候,是哪一个或者几个 bit 引起的,有时候放宽一点判断的条件即可,一般是通过修改上下限来达到,具体可以参考代码里面 bit 值的判断地方。
3、getevent 有时候无法确定是内核按键判断出错,还是 android 层没有响应某个按键, 可以在串口下输入getevent 调试命令,该命令会打出驱动上报的所有 input 事件,如果按遥控器有打印,并且键值正确,那说明是 android 响应的问题。
shell@rk3399:/ # getevent
add device 1: /dev/input/event0
name: "ff680000.pwm"
/dev/input/event0: 0001 006c 00000001
/dev/input/event0: 0000 0000 00000000
/dev/input/event0: 0001 006c 00000000
/dev/input/event0: 0000 0000 00000000
以上是在调试平台输入 getevent 的效果,最前面会列出所有的 input 设备,按的时候会上报事件,其中 0x6c 是上报的 linux 键值,后面的 1 代表按下,如果是 0 则代表弹起。