紅外遙控的發射電路是採用紅外發光二極管來發出經過調製的紅外光波;紅外接收電路由紅外接收二極管、三極管或硅光電池組成,它們將紅外發射器發射的紅外光轉換爲相應的電信號,再送後置放大器。鑑於家用電器的品種多樣化和用戶的使用特點,生產廠家對紅外遙控編碼進行了嚴格的規範編碼,這些編碼各不相同,從而形成不同的編碼方式,統一稱爲紅外遙控器編碼傳輸協議。到目前爲止,紅外遙控協議已多達十種, 如: 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 讀取相應的寄存器就知道這些高低電平的時間,根據協議就可以解碼出紅外的用戶碼和鍵值碼出來。
1、查看遙控器的用戶碼和鍵值,供應商給的可能是反碼,也有可能不正確,最好是自己打印出來看看是啥。
打開紅外打印功能有以下兩種方式,內核打印可以用串口,也可以在adb中使用指令 # cat proc/kmsg
(1)通過指令打開紅外接收的打印功能,然後按遙控器按鍵,就可以在內核打印中看到用戶碼和鍵值。
root@rk3288:/ # cat sys/module/rockchip_pwm_remotectl/parameters/code_print
0
root@rk3288:/ # echo 1 > sys/module/rockchip_pwm_remotectl/parameters/code_print
(2)在紅外接收的源碼中,給下面變量賦值,也可以打印用戶碼和鍵值,但需要重新編譯燒錄內核
path:kernel/drivers/input/remotectl/rockchip_pwm_remotectl.c
static int rk_remote_print_code = 1;
Kernel修改:
--- a/arch/arm/boot/dts/rk3288-evb-android-rk808-hdmi.dts
+++ b/arch/arm/boot/dts/rk3288-evb-android-rk808-hdmi.dts
@@ -43,6 +43,7 @@
/dts-v1/;
#include "rk3288-evb.dtsi"
#include "rk3288-android.dtsi"
+#include <dt-bindings/input/input.h> //czd: support IR-Remote.
/ {
compatible = "rockchip,rk3288-evb-android-rk808-hdmi", "rockchip,rk3288";
@@ -397,3 +398,71 @@
pinctrl-0 = <&pwm1_pin_pull_down>;
};
+//add by czd for support IR-Remote on start
+&pwm2 {
+ status = "okay";
+ compatible = "rockchip,remotectl-pwm";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm2_pin>;
+ remote_pwm_id = <2>;
+ handle_cpu_id = <1>;
+ interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+ remote_support_psci = <1>;
+
+ ir_key1{
+ rockchip,usercode = <0xbd02>;
+ rockchip,key_table =
+ <0x2f KEY_BACK>,
+ <0x35 KEY_UP>,
......
}
Android層修改:
zwei@ubt144c:/work/zwei/czd/rk3288_7.1_mid/device/rockchip/common$ git diff
diff --git a/device.mk b/device.mk
index 37e73d5..fc82c24 100755
--- a/device.mk
+++ b/device.mk
@@ -101,7 +101,7 @@ PRODUCT_COPY_FILES += \
device/rockchip/common/ueventd.rockchip.rc:root/ueventd.$(TARGET_BOARD_HARDWARE).rc \
device/rockchip/common/media_profiles_default.xml:system/etc/media_profiles_default.xml \
device/rockchip/common/rk29-keypad.kl:system/usr/keylayout/rk29-keypad.kl \
- device/rockchip/common/ff680030_pwm.kl:system/usr/keylayout/ff680030_pwm.kl \
+ device/rockchip/common/ff680030_pwm.kl:system/usr/keylayout/ff680020_pwm.kl \
device/rockchip/common/alarm_filter.xml:system/etc/alarm_filter.xml \
並且需要添加對應按鍵的linux code和android code到ff680020_pwm.kl文件。
a)打開打印鍵值的調試開關:
echo 1 > sys/module/rockchip_pwm_remotectl/parameters/code_print
b) 按遙控器的按鍵,記錄下對應的鍵值
[19634.735833] GET USERCODE=0xbd02
[19634.762463] RMC_GETDATA=e9
說明:該遙控器的 usercode 是 0xbd02,向下鍵的鍵值就是 0xe9
有時候無法確定是內核按鍵判斷出錯,還是 android 層沒有響應某個按鍵,可以在串口下輸入getevent 調試命令,該命令會打印出驅動上報的所有 input 事件,如果按遙控器有打印,並且鍵值正確,那說明是 android 響應的問題。
rk3288:/ # getevent
add device 1: /dev/input/event1
name: "rk29-keypad"
add device 2: /dev/input/event0
name: "ff680020.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
/dev/input/event0: 0001 009e 00000001
cmd輸入 getevent,最前面會列出所有的 input 設備,按的時候會上報
事件,其中 0x6c 是上報的 linux 鍵值,後面的 1 代表按下,如果是 0 則代表彈起。
如果沒有getevent到事件,無鍵值上報,adb執行cat proc/interrupts可以查看中斷interrupt的註冊使用情況:(第一列的數字對應註冊的中斷號,第二第三第四第五列數字分別表示中斷在哪一個cpu上處理,有中斷過來的話,對應的cpu下的數字相應自加1)
rk3288:/ # cat proc/interrupts
CPU0 CPU1 CPU2 CPU3
16: 0 0 0 0 GIC 29 Edge arch_timer
17: 118303 97092 81417 115531 GIC 30 Edge arch_timer
20: 0 0 0 0 GIC 98 Level rk_timer
25: 0 0 0 0 GIC 34 Level ff250000.dma-controller
26: 0 0 0 0 GIC 35 Level ff250000.dma-controller
27: 367 0 0 0 GIC 32 Level ff600000.dma-controller
28: 0 0 0 0 GIC 33 Level ff600000.dma-controller
29: 0 0 0 0 GIC 64 Level dw-mci
30: 14838 0 0 0 GIC 65 Level dw-mci
31: 34851 0 0 0 GIC 67 Level dw-mci
32: 4565 0 0 0 GIC 68 Level ff100000.saradc
33: 747 0 0 0 GIC 92 Level ff650000.i2c
34: 0 0 0 0 GIC 94 Level ff140000.i2c
35: 153 0 0 0 GIC 95 Level ff150000.i2c
37: 0 0 0 0 GIC 69 Level rockchip_thermal
38: 4352 0 0 0 GIC 59 Level eth0
39: 0 0 0 0 GIC 60 Level eth0
40: 0 0 0 0 GIC 56 Level ehci_hcd:usb2
41: 0 0 0 0 GIC 73 Level ohci_hcd:usb3
42: 151 0 0 0 GIC 57 Level ff540000.usb, dwc2_hsotg:usb1
43: 489 0 0 0 GIC 55 Level dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb4
44: 24 0 0 0 GIC 93 Level ff660000.i2c
45: 0 1 0 0 GIC 110 Level rk_pwm_irq
關於鍵值轉換說明:鍵值經過兩次轉換到達安卓上層:
在Dts配置:(16進制寄存器值轉換成linux code的宏,
0x35 KEY_UP
其中0x35爲遙控鍵值碼;
KEY_UP宏定義在include/dt-bindings/input/linux-event-codes.h文件)
這樣遙控器紅外層到linux層的鍵值映射就完成了。
input輸入子系統上報鍵值(adb shell && getevent查看):
/dev/input/event0: 0001 0067 00000001
/dev/input/event0: 0000 0000 00000000
/dev/input/event0: 0001 0067 00000000
/dev/input/event0: 0000 0000 00000000
其中 0x67 是上報的 linux 鍵值(include/dt-bindings/input/linux-event-codes.h文件的10進制轉成的16進制數,如0067是由103轉換而來),後面的 1 代表按下,如果是 0 則代表彈起。
.kl文件鍵值轉換:android kl(key layout)文件是一個映射文件,是標準linux與anroid的鍵值映射文件。adb使用dumpsys input命令可以查看當前設備對應使用的是哪個kl文件,(RK平臺的 kl 文件一般是放在\device\rockchip\common(如rk3288) 目錄下,與getevent獲取的name屬性名字一樣的文件(只不過name中的“.”要換成 kl 中的“_”)。每個芯片的 kl 文件名字不一樣,需要注意,一般在\device\rockchip\common\device.mk文件配置。),如果沒有配置對應設備的.kl文件,則會默認使用Generic.kl這個kl
==>
rk3288:/ # getevent
add device 1: /dev/input/event1
name: "rk29-keypad"
add device 2: /dev/input/event0
name: "ff680020.pwm"
則對應需要kl文件爲:ff680020_pwm.kl,目錄在/system/usr/keylayout/,可以push進去驗證
130|rk3288:/ $ dumpsys input
2: ff680020.pwm
Classes: 0x00000401
Path: /dev/input/event0
Descriptor: d2c52ff0f656fac4cd7b7a118d575e0109a9fe1c
Location: gpio-keys/remotectl
ControllerNumber: 0
UniqueId:
Identifier: bus=0x0019, vendor=0x0001, product=0x0001, version=0x0100
KeyLayoutFile: /system/usr/keylayout/ff680020_pwm.kl
KeyCharacterMapFile: /system/usr/keychars/Generic.kcm
ConfigurationFile:
HaveKeyboardLayoutOverlay: false
kl文件內容:
key 28 ENTER
key 116 POWER
key 158 BACK、
說明:
key是固定的
28是linux code值
ENTER是Android code值
這樣kernel層到Android層的鍵值映射就完成了。