• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &param);
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, &param); //irda clk:26M
224 
225 	param = PWD_IRDA_CLK_BIT;
226 	sddev_control(DD_DEV_TYPE_ICU, CMD_CLK_PWR_UP, &param);//clk power up
227 
228 	param = GFUNC_MODE_IRDA;
229 	sddev_control(DD_DEV_TYPE_GPIO, CMD_GPIO_ENABLE_SECOND, &param); //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