Commit | Line | Data |
---|---|---|
635abb70 JH |
1 | /* |
2 | * ImgTec IR Decoder setup for NEC protocol. | |
3 | * | |
4 | * Copyright 2010-2014 Imagination Technologies Ltd. | |
2ac6f630 JH |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2 of the License, or (at your | |
9 | * option) any later version. | |
635abb70 JH |
10 | */ |
11 | ||
12 | #include "img-ir-hw.h" | |
42f5e630 | 13 | #include <linux/bitrev.h> |
635abb70 JH |
14 | |
15 | /* Convert NEC data to a scancode */ | |
120703f9 DH |
16 | static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol, |
17 | u32 *scancode, u64 enabled_protocols) | |
635abb70 JH |
18 | { |
19 | unsigned int addr, addr_inv, data, data_inv; | |
20 | /* a repeat code has no data */ | |
21 | if (!len) | |
22 | return IMG_IR_REPEATCODE; | |
23 | if (len != 32) | |
24 | return -EINVAL; | |
25 | /* raw encoding: ddDDaaAA */ | |
26 | addr = (raw >> 0) & 0xff; | |
27 | addr_inv = (raw >> 8) & 0xff; | |
28 | data = (raw >> 16) & 0xff; | |
29 | data_inv = (raw >> 24) & 0xff; | |
30 | if ((data_inv ^ data) != 0xff) { | |
31 | /* 32-bit NEC (used by Apple and TiVo remotes) */ | |
42f5e630 DH |
32 | /* scan encoding: as transmitted, MSBit = first received bit */ |
33 | *scancode = bitrev8(addr) << 24 | | |
34 | bitrev8(addr_inv) << 16 | | |
35 | bitrev8(data) << 8 | | |
36 | bitrev8(data_inv); | |
635abb70 JH |
37 | } else if ((addr_inv ^ addr) != 0xff) { |
38 | /* Extended NEC */ | |
39 | /* scan encoding: AAaaDD */ | |
40 | *scancode = addr << 16 | | |
41 | addr_inv << 8 | | |
42 | data; | |
43 | } else { | |
44 | /* Normal NEC */ | |
45 | /* scan encoding: AADD */ | |
46 | *scancode = addr << 8 | | |
47 | data; | |
48 | } | |
120703f9 | 49 | *protocol = RC_TYPE_NEC; |
635abb70 JH |
50 | return IMG_IR_SCANCODE; |
51 | } | |
52 | ||
53 | /* Convert NEC scancode to NEC data filter */ | |
54 | static int img_ir_nec_filter(const struct rc_scancode_filter *in, | |
55 | struct img_ir_filter *out, u64 protocols) | |
56 | { | |
57 | unsigned int addr, addr_inv, data, data_inv; | |
58 | unsigned int addr_m, addr_inv_m, data_m, data_inv_m; | |
59 | ||
60 | data = in->data & 0xff; | |
61 | data_m = in->mask & 0xff; | |
62 | ||
63 | if ((in->data | in->mask) & 0xff000000) { | |
64 | /* 32-bit NEC (used by Apple and TiVo remotes) */ | |
42f5e630 DH |
65 | /* scan encoding: as transmitted, MSBit = first received bit */ |
66 | addr = bitrev8(in->data >> 24); | |
67 | addr_m = bitrev8(in->mask >> 24); | |
68 | addr_inv = bitrev8(in->data >> 16); | |
69 | addr_inv_m = bitrev8(in->mask >> 16); | |
70 | data = bitrev8(in->data >> 8); | |
71 | data_m = bitrev8(in->mask >> 8); | |
72 | data_inv = bitrev8(in->data >> 0); | |
73 | data_inv_m = bitrev8(in->mask >> 0); | |
635abb70 JH |
74 | } else if ((in->data | in->mask) & 0x00ff0000) { |
75 | /* Extended NEC */ | |
76 | /* scan encoding AAaaDD */ | |
77 | addr = (in->data >> 16) & 0xff; | |
78 | addr_m = (in->mask >> 16) & 0xff; | |
79 | addr_inv = (in->data >> 8) & 0xff; | |
80 | addr_inv_m = (in->mask >> 8) & 0xff; | |
81 | data_inv = data ^ 0xff; | |
82 | data_inv_m = data_m; | |
83 | } else { | |
84 | /* Normal NEC */ | |
85 | /* scan encoding: AADD */ | |
86 | addr = (in->data >> 8) & 0xff; | |
87 | addr_m = (in->mask >> 8) & 0xff; | |
88 | addr_inv = addr ^ 0xff; | |
89 | addr_inv_m = addr_m; | |
90 | data_inv = data ^ 0xff; | |
91 | data_inv_m = data_m; | |
92 | } | |
93 | ||
94 | /* raw encoding: ddDDaaAA */ | |
95 | out->data = data_inv << 24 | | |
96 | data << 16 | | |
97 | addr_inv << 8 | | |
98 | addr; | |
99 | out->mask = data_inv_m << 24 | | |
100 | data_m << 16 | | |
101 | addr_inv_m << 8 | | |
102 | addr_m; | |
103 | return 0; | |
104 | } | |
105 | ||
106 | /* | |
107 | * NEC decoder | |
108 | * See also http://www.sbprojects.com/knowledge/ir/nec.php | |
109 | * http://wiki.altium.com/display/ADOH/NEC+Infrared+Transmission+Protocol | |
110 | */ | |
111 | struct img_ir_decoder img_ir_nec = { | |
112 | .type = RC_BIT_NEC, | |
113 | .control = { | |
114 | .decoden = 1, | |
115 | .code_type = IMG_IR_CODETYPE_PULSEDIST, | |
116 | }, | |
117 | /* main timings */ | |
118 | .unit = 562500, /* 562.5 us */ | |
119 | .timings = { | |
120 | /* leader symbol */ | |
121 | .ldr = { | |
122 | .pulse = { 16 /* 9ms */ }, | |
123 | .space = { 8 /* 4.5ms */ }, | |
124 | }, | |
125 | /* 0 symbol */ | |
126 | .s00 = { | |
127 | .pulse = { 1 /* 562.5 us */ }, | |
128 | .space = { 1 /* 562.5 us */ }, | |
129 | }, | |
130 | /* 1 symbol */ | |
131 | .s01 = { | |
132 | .pulse = { 1 /* 562.5 us */ }, | |
133 | .space = { 3 /* 1687.5 us */ }, | |
134 | }, | |
135 | /* free time */ | |
136 | .ft = { | |
137 | .minlen = 32, | |
138 | .maxlen = 32, | |
139 | .ft_min = 10, /* 5.625 ms */ | |
140 | }, | |
141 | }, | |
142 | /* repeat codes */ | |
143 | .repeat = 108, /* 108 ms */ | |
144 | .rtimings = { | |
145 | /* leader symbol */ | |
146 | .ldr = { | |
147 | .space = { 4 /* 2.25 ms */ }, | |
148 | }, | |
149 | /* free time */ | |
150 | .ft = { | |
151 | .minlen = 0, /* repeat code has no data */ | |
152 | .maxlen = 0, | |
153 | }, | |
154 | }, | |
155 | /* scancode logic */ | |
156 | .scancode = img_ir_nec_scancode, | |
157 | .filter = img_ir_nec_filter, | |
158 | }; |