1 红外遥控协议
1.1 基本概念
1)NEC协议,采用PWM方式调制。38KHz载波,一般是由引导码+地址码+地址反码+数据+数据反码构成。
遥控接收头端收到的信号为:逻辑1是560us低+1680us高,逻辑0是560us低+560us高。
地址:u32 >> 24
地址反码:u32 >> 16
数据:u32 >> 8
数据反码:u32 & 0xff
2)Philips RC-5协议,采用PPM方式调制
1.2 STM32 TIM解码红外信号
输入捕获模式下:当捕获单元捕获到外来有效信号边沿事件(通过TIM1 CH1 Capture Compare Enable Register = 0xB设置上升沿和下降沿捕获,STM32库使用宏TIM_ICPolarity_BothEdge = 0x000A配置双边沿触发捕获),将此刻计数器的值锁存到CCR(Capture Compare Register,16bit)影子寄存器并自动将CCR影子寄存器的值拷贝进CCR预装寄存器,以供用户读取。DMA传输方式就是将CCR预装寄存器中的计数值传输到内存中。CCR寄存器中的计数值与上一次的计数值相减 x 计数频率的倒数 = 高电平或者低电平信号宽度。
输入捕获采样的频率就是定时器经过预分配器(PSC)之后的频率,譬如STM32F1 TIM1 CH1的计数器频率等于4 x 1.786KHz (560us) = 72MHz/(Prescaler + 1),那么计数器计数每增加4个就表示一个bit。解码时,连续2次计数间隔相等时表示0,连续2次计数间隔不等时表示1。
另外一种方式是将TIM的计数频率配置成1MHz,则每1us计数值加1。
2 Android GPIO IR配置
2.1 Linux设备树配置
Add gpio-ir-recv platform device dts and pinctrl as shown below:
ir: ir-receiver {
compatible = "gpio-ir-receiver";
gpios = <&msmgpio 52 1>;
linux,rc-map-name = "rc-YOUR_DEVICE-nec";
pinctrl-names = "default";
pinctrl-0 = <&oem_gpio_ir_pu>;
oem,disable_ipc;
};
oem_gpio_ir {
qcom,pins = <&gp 52>;
qcom,num-grp-pins = <1>;
qcom,pin-func = <1>;
label = "oem_gpio_ir";
oem_gpio_ir_pu: default {
drive-strength = <16>;
bias-pull-up;
};
};
2.2 Kernel Config
CONFIG_RC_CORE=y
CONFIG_IR_NEC_DECODER=y
CONFIG_MEDIA_RC_SUPPORT=y
CONFIG_IR_GPIO_CIR=y
2.3 Keys Timeout
2.3.1 Kernel Hardcode
diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
index 5c42750..1be6592 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/ir-raw.c
@@ -116,7 +116,8 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_eve
now = ktime_get();
delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event));
- delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]);
+ //delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]);
+ delay = MS_TO_NS(250); // 500
2.3.2 Disable Framework Reset Timeout
diff --git
services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index dfe5d3d..c40bd8f 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -1050,6 +1050,7 @@ static const int32_t GAMEPAD_KEYCODES[] = {
status_t EventHub::openDeviceLocked(const char *devicePath) {
char buffer[80];
+ char oem_cache_devname[80];
ALOGV("Opening device: %s", devicePath);
@@ -1067,6 +1068,7 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.name.setTo(buffer);
+ strcpy(oem_cache_devname, buffer);
}
// Check to see if the device is on our excluded list
@@ -1270,9 +1272,11 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
// Disable kernel key repeat since we handle it ourselves
unsigned int repeatRate[] = {0,0};
- if (ioctl(fd, EVIOCSREP, repeatRate)) {
- ALOGW("Unable to disable kernel key repeat for %s: %s",
- devicePath, strerror(errno));
- }
+ if (0 != strcmp(oem_cache_devname, "gpio_ir_recv")) {
+ if (ioctl(fd, EVIOCSREP, repeatRate)) {
+ ALOGW("Unable to disable kernel key repeat for %s: %s",
+ devicePath, strerror(errno));
+ }
+ }
}