1 /*
2 // Copyright (C) 2022 Beken Corporation
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <common/bk_include.h>
16 #include "bk_arm_arch.h"
17
18 #include "irda.h"
19 #include "bk_irda.h"
20
21 #include "bk_drv_model.h"
22 #include <driver/int.h>
23 #include "bk_icu.h"
24 #include "bk_gpio.h"
25 #include "bk_sys_ctrl.h"
26 #include "bk_timer.h"
27 #include <os/os.h>
28 #include "icu_driver.h"
29
30 struct IR_KEY_ST {
31 beken_queue_t IRkey_mq;
32
33 UINT16 IR_UserCode;
34 UINT8 valid_flag;
35 UINT8 IR_key_code;
36 UINT8 repeat_flag;
37 UINT8 repeat_cnt;
38 UINT8 timer_cnt;
39 };
40
41 static struct IR_KEY_ST IR_key = {0};
42
43
44 static UINT32 irda_ctrl(UINT32 cmd, void *param);
45 static const DD_OPERATIONS irda_op = {
46 NULL,
47 NULL,
48 NULL,
49 NULL,
50 irda_ctrl
51 };
52
53
IR_send_key(UINT32 msg)54 static int IR_send_key(UINT32 msg)
55 {
56 if (NULL != IR_key.IRkey_mq)
57 return rtos_push_to_queue(&IR_key.IRkey_mq, (void *)&msg, sizeof(msg));
58 else
59 return -1;
60 }
61
irda_key_timer_hdl(UINT8 param)62 static void irda_key_timer_hdl(UINT8 param)
63 {
64 #define SND_KEY (1 << 0)
65 #define STOP_TIMER (1 << 1)
66
67 UINT32 channel = IRDA_KEY_HTIMER_CHNAL;
68 static UINT8 hold_flag = 0;
69 UINT8 key_type = 0;
70 UINT8 op_flag = 0;
71
72 IR_key.timer_cnt ++;
73 if (IR_key.timer_cnt > IR_key.repeat_cnt) {
74 if (IR_key.repeat_cnt < KEY_SHORT_CNT) {
75 key_type = IR_KEY_TYPE_SHORT;
76 op_flag = SND_KEY | STOP_TIMER;
77 } else if (IR_key.repeat_cnt < KEY_LONG_CNT) {
78 key_type = IR_KEY_TYPE_LONG;
79 op_flag = SND_KEY | STOP_TIMER;
80 } else {
81 if (hold_flag == 0) {
82 key_type = IR_KEY_TYPE_HOLD;
83 op_flag = SND_KEY | STOP_TIMER;
84 } else
85 op_flag = STOP_TIMER;
86 }
87 hold_flag = 0;
88 } else {
89 if (IR_key.repeat_cnt >= KEY_HOLD_CNT) {
90 hold_flag = 1;
91 op_flag = SND_KEY;
92
93 key_type = IR_KEY_TYPE_HOLD;
94 IR_key.repeat_cnt = KEY_LONG_CNT;
95 IR_key.timer_cnt = KEY_LONG_CNT;
96 }
97 }
98
99 if (op_flag & SND_KEY)
100 IR_send_key(GENERATE_KEY(key_type, IR_key.IR_key_code));
101 if (op_flag & STOP_TIMER)
102 sddev_control(DD_DEV_TYPE_TIMER, CMD_TIMER_UNIT_DISABLE, &channel);
103 }
104
start_irda_handle_timer(UINT32 period)105 static void start_irda_handle_timer(UINT32 period)
106 {
107 timer_param_t param;
108
109 param.channel = IRDA_KEY_HTIMER_CHNAL;
110 param.div = 1;
111 param.period = period;
112 param.t_Int_Handler = irda_key_timer_hdl;
113
114 sddev_control(DD_DEV_TYPE_TIMER, CMD_TIMER_INIT_PARAM, ¶m);
115 }
116
irda_active(UINT8 enable)117 static void irda_active(UINT8 enable)
118 {
119 UINT32 value;
120
121 value = REG_READ(IRDA_CTRL);
122 if (enable)
123 value |= IRDA_NEC_EN;
124 else
125 value &= ~IRDA_NEC_EN;
126 REG_WRITE(IRDA_CTRL, value);
127 }
128
irda_set_polarity(UINT8 polarity)129 static void irda_set_polarity(UINT8 polarity)
130 {
131 UINT32 value;
132
133 value = REG_READ(IRDA_CTRL);
134 if (polarity)
135 value |= IRDA_POLARITY;
136 else
137 value &= ~IRDA_POLARITY;
138 REG_WRITE(IRDA_CTRL, value);
139 }
140
irda_set_clk(UINT16 clk)141 static void irda_set_clk(UINT16 clk)
142 {
143 UINT32 value;
144
145 value = REG_READ(IRDA_CTRL);
146 value &= ~(CLK_DIVID_MASK << CLK_DIVID_POSI);
147 value |= (clk << CLK_DIVID_POSI);
148 REG_WRITE(IRDA_CTRL, value);
149 }
irda_set_int_mask(UINT8 int_en_bits)150 static void irda_set_int_mask(UINT8 int_en_bits)
151 {
152 UINT32 value;
153 value = REG_READ(IRDA_INT_MASK);
154 value &= ~INT_MASK_EN;
155 value |= int_en_bits;
156 REG_WRITE(IRDA_INT_MASK, value);
157 }
158
irda_ctrl(UINT32 cmd,void * param)159 static UINT32 irda_ctrl(UINT32 cmd, void *param)
160 {
161 UINT32 ret = IRDA_SUCCESS;
162
163 switch (cmd) {
164 case IRDA_CMD_ACTIVE:
165 irda_active(*(UINT8 *)param);
166 break;
167 case IRDA_CMD_SET_POLARITY:
168 irda_set_polarity(*(UINT8 *)param);
169 break;
170 case IRDA_CMD_SET_CLK:
171 irda_set_clk(*(UINT16 *)param);
172 break;
173 case IRDA_CMD_SET_INT_MASK:
174 irda_set_int_mask(*(UINT8 *)param);
175 break;
176 default:
177 ret = IRDA_FAILURE;
178 break;
179 }
180
181 return ret;
182 }
183
IR_get_key(void * buffer,unsigned long size,INT32 timeout)184 long IR_get_key(void *buffer, unsigned long size, INT32 timeout)
185 {
186 bk_err_t ret;
187
188 ret = rtos_pop_from_queue(&IR_key.IRkey_mq, buffer, timeout);
189
190 //TODO double check whether need to to return value convert!!!
191 return ret;
192 }
193
irda_init(void)194 void irda_init(void)
195 {
196 bk_int_isr_register(INT_SRC_IRDA, irda_isr, NULL);
197 sddev_register_dev(DD_DEV_TYPE_IRDA, (DD_OPERATIONS *)&irda_op);
198 }
199
irda_exit(void)200 void irda_exit(void)
201 {
202 sddev_unregister_dev(DD_DEV_TYPE_IRDA);
203 }
204
set_irda_usrcode(UINT16 ir_usercode)205 void set_irda_usrcode(UINT16 ir_usercode)
206 {
207 IR_key.IR_UserCode = ir_usercode;
208 }
209
Irda_init_app(void)210 void Irda_init_app(void)
211 {
212 bk_err_t ret;
213 UINT32 param;
214
215 IR_key.valid_flag = 0;
216 ret = rtos_init_queue(&IR_key.IRkey_mq, "ir_mq", 4, 3);
217 if (kNoErr != ret) {
218 os_printf("create ir mq error!!\r\n");
219 return;
220 }
221
222 param = PCLK_POSI_IRDA;
223 sddev_control(DD_DEV_TYPE_ICU, CMD_CONF_PCLK_26M, ¶m); //irda clk:26M
224
225 param = PWD_IRDA_CLK_BIT;
226 sddev_control(DD_DEV_TYPE_ICU, CMD_CLK_PWR_UP, ¶m);//clk power up
227
228 param = GFUNC_MODE_IRDA;
229 sddev_control(DD_DEV_TYPE_GPIO, CMD_GPIO_ENABLE_SECOND, ¶m); //gpio config
230
231 irda_set_polarity(0);//polarity set: low effective
232 irda_active(1);//NEC IRDA enable
233 irda_set_clk(0x3921);//irda_clk*562.5 (26*562.5 = 0x3921)
234 irda_set_int_mask(IRDA_RIGHT_INT_MASK | IRDA_REPEAT_INT_MASK | IRDA_END_INT_MASK);
235
236 /*interrupt setting about IRDA*/
237 icu_enable_irda_interrupt();
238 icu_enable_irq();
239
240 }
241
242
irda_isr(void)243 void irda_isr(void)
244 {
245 #define REPEAT_KEY_TIME_INTERVAL 112 /*bigger than 108 ms*/
246
247 UINT32 irda_int;
248 UINT32 end_int, right_int, repeat_int;
249 UINT32 tmp;
250
251 irda_int = REG_READ(IRDA_INT);
252 end_int = irda_int & IRDA_END_INT;
253 right_int = irda_int & IRDA_RIGHT_INT;
254 repeat_int = irda_int & IRDA_REPEAT_INT;
255 REG_WRITE(IRDA_INT, irda_int);
256 if (right_int) {
257 //leader code is received
258 IR_key.valid_flag = 1;
259 IR_key.repeat_flag = 0;
260 IR_key.repeat_cnt = 0;
261 }
262
263 if (end_int) {
264 //custom code and data code are received (32bits)
265 if (IR_key.valid_flag) {
266 tmp = REG_READ(RX_FIFO_DOUT);
267
268 BK_LOG_RAW("ir value:%x\r\n", tmp);
269
270 if (((tmp & USERCODE_MASK) != IR_key.IR_UserCode) ||
271 ((((tmp & KEY_CODE_INVERS_MASK) >> KEY_CODE_INVERS_SHIFT) ^ ((tmp & KEY_CODE_MASK) >> KEY_CODE_SHIFT)) != 0xff)) {
272 BK_LOG_RAW("invalid ir value\r\n");
273 IR_key.valid_flag = 0;
274 return;
275 }
276
277 IR_key.IR_key_code = (tmp & KEY_CODE_MASK) >> KEY_CODE_SHIFT;
278 IR_key.timer_cnt = 0;
279 start_irda_handle_timer(REPEAT_KEY_TIME_INTERVAL);
280 }
281 }
282 if (repeat_int) {
283 //repeat code is received
284 IR_key.repeat_flag = 1;
285 IR_key.repeat_cnt++;
286 }
287 }
288
289