1 /*
2 * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3 */
4
5 #include <stdint.h>
6
7 #include "amp_config.h"
8 #include "amp_defines.h"
9 #include "aos_hal_gpio.h"
10 #include "board_mgr.h"
11 #include "be_inl.h"
12
13 #define MOD_STR "IR"
14
ir_learn_mode(uint32_t scl_pin,uint32_t sda_pin)15 static void ir_learn_mode(uint32_t scl_pin, uint32_t sda_pin)
16 {
17 gpio_i2c_reset(scl_pin, sda_pin);
18 gpio_i2c_delay_10us(4);
19
20 gpio_i2c_set_low(scl_pin);
21 gpio_i2c_delay_10us(8);
22 gpio_i2c_set_high(scl_pin);
23
24 jse_osal_delay(20);
25 gpio_i2c_start(scl_pin, sda_pin);
26 gpio_i2c_delay_10us(4);
27
28 gpio_i2c_write_byte(scl_pin, sda_pin, 0x30);
29 gpio_i2c_delay_10us(4);
30
31 gpio_i2c_write_byte(scl_pin, sda_pin, 0x20);
32 gpio_i2c_delay_10us(4);
33
34 gpio_i2c_write_byte(scl_pin, sda_pin, 0x50);
35 gpio_i2c_delay_10us(8);
36
37 gpio_i2c_stop(scl_pin, sda_pin);
38 gpio_i2c_delay_10us(4);
39
40 gpio_i2c_reset(scl_pin, sda_pin);
41 gpio_i2c_delay_10us(4);
42 }
43
ir_learn_read(uint32_t scl_pin,uint32_t sda_pin,uint8_t * buff)44 static int8_t ir_learn_read(uint32_t scl_pin, uint32_t sda_pin, uint8_t *buff)
45 {
46 uint8_t value = 0;
47 uint8_t i = 0;
48 uint8_t checksum = 0;
49 gpio_i2c_reset(scl_pin, sda_pin);
50 gpio_i2c_delay_10us(4);
51 gpio_i2c_set_low(scl_pin);
52 gpio_i2c_delay_10us(8);
53 gpio_i2c_set_high(scl_pin);
54 jse_osal_delay(20);
55
56 gpio_i2c_start(scl_pin, sda_pin);
57 gpio_i2c_delay_10us(4);
58 gpio_i2c_write_byte(scl_pin, sda_pin, 0x30);
59 gpio_i2c_delay_10us(4);
60 gpio_i2c_write_byte(scl_pin, sda_pin, 0x62);
61 gpio_i2c_delay_10us(4);
62
63 gpio_i2c_start(scl_pin, sda_pin);
64 gpio_i2c_delay_10us(4);
65 gpio_i2c_write_byte(scl_pin, sda_pin, 0x31);
66 gpio_i2c_delay_10us(4);
67 value = gpio_i2c_read_byte(scl_pin, sda_pin);
68 gpio_i2c_delay_10us(4);
69 if (0x00 != value) {
70 gpio_i2c_stop(scl_pin, sda_pin);
71 gpio_i2c_delay_10us(4);
72 gpio_i2c_reset(scl_pin, sda_pin);
73 gpio_i2c_delay_10us(4);
74 return -1;
75 }
76 buff[i] = value;
77 checksum = 0xc3;
78 for (i = 1; i < 230; i++) {
79 value = gpio_i2c_read_byte(scl_pin, sda_pin);
80 gpio_i2c_delay_10us(4);
81 buff[i] = value;
82 checksum += value;
83 }
84 value = gpio_i2c_read_byte(scl_pin, sda_pin);
85 gpio_i2c_delay_10us(4);
86 gpio_i2c_stop(scl_pin, sda_pin);
87 gpio_i2c_delay_10us(4);
88 gpio_i2c_reset(scl_pin, sda_pin);
89 gpio_i2c_delay_10us(4);
90 return 0;
91 }
92
ir_learn_start(uint32_t scl_pin,uint32_t sda_pin,uint32_t busy_bin,uint8_t buff[232])93 static int32_t ir_learn_start(uint32_t scl_pin, uint32_t sda_pin,
94 uint32_t busy_bin, uint8_t buff[232])
95 {
96 uint8_t sumValue = 0;
97 int32_t count = 0;
98 int8_t ret = -1;
99 uint8_t i = 0;
100 uint8_t tmp[512] = {0x00};
101 gpio_i2c_init(scl_pin, sda_pin);
102 gpio_i2c_set_in(busy_bin);
103 ir_learn_mode(scl_pin, sda_pin);
104 jse_osal_delay(50);
105 while (!gpio_i2c_read_pin(busy_bin)) gpio_i2c_delay_10us(10);
106 ret = ir_learn_read(scl_pin, sda_pin, tmp);
107 if (0 != ret) {
108 return -1;
109 }
110 buff[0] = 0x30;
111 sumValue += buff[0];
112 buff[1] = 0x03;
113 sumValue += buff[1];
114 for (i = 1; i < 231; i++) {
115 buff[i + 1] = tmp[i];
116 sumValue += tmp[i];
117 }
118 buff[231] = sumValue;
119 return 232;
120 }
121
ir_counts(gpio_dev_t * gpio,uint8_t level)122 static uint32_t ir_counts(gpio_dev_t *gpio, uint8_t level)
123 {
124 int8_t ret = 0;
125 uint32_t value = 0;
126 uint32_t counts = 0;
127 do {
128 ret = aos_hal_gpio_input_get(gpio, &value);
129 counts += 1;
130 jse_osal_delay10us();
131 } while ((0 == ret) && (value == level));
132 return counts;
133 }
134
ir_nec(gpio_dev_t * gpio)135 static uint32_t ir_nec(gpio_dev_t *gpio)
136 {
137 uint32_t counts = 0;
138 uint32_t value = 0;
139 uint8_t i = 0;
140 uint8_t j = 0;
141 /*9ms*/
142 counts = ir_counts(gpio, 0);
143 if (counts < 850 || counts > 950) {
144 return 0;
145 }
146 /*4.5ms*/
147 counts = ir_counts(gpio, 1);
148 if (counts < 400 || counts > 500) {
149 return 0;
150 }
151 for (i = 0; i < 4; ++i) {
152 for (j = 0; j < 8; ++j) {
153 value <<= 1;
154 counts = ir_counts(gpio, 0);
155 if (counts < 30 || counts > 100) {
156 return 0;
157 }
158 counts = ir_counts(gpio, 1);
159 if (counts > 130 && counts < 200) {
160 value |= 1;
161 } else if (counts < 30 || counts > 100) {
162 return 0;
163 }
164 }
165 }
166 return value;
167 }
168
native_ir_open(duk_context * ctx)169 static duk_ret_t native_ir_open(duk_context *ctx)
170 {
171 int8_t ret = -1;
172 item_handle_t gpio_handle;
173 gpio_handle.handle = NULL;
174 gpio_dev_t *gpio_device = NULL;
175
176 if (!duk_is_string(ctx, 0)) {
177 amp_warn(MOD_STR, "parameter must be string");
178 goto out;
179 }
180 const char *id = duk_get_string(ctx, 0);
181 ret = board_attach_item(MODULE_GPIO, id, &gpio_handle);
182 if (0 != ret) {
183 amp_error(MOD_STR, "board_attach_item fail!\n");
184 goto out;
185 }
186 amp_debug(MOD_STR, "ir handle:%u\n", gpio_handle.handle);
187 gpio_device = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
188 if (NULL == gpio_device) {
189 amp_error(MOD_STR, "board_get_node_by_handle fail!\n");
190 goto out;
191 }
192 ret = aos_hal_gpio_init(gpio_device);
193 if (0 != ret) {
194 amp_error(MOD_STR, "aos_hal_gpio_init fail!\n");
195 goto out;
196 }
197 gpio_device->priv = NULL;
198 out:
199 if (0 != ret) {
200 duk_push_pointer(ctx, NULL);
201 board_disattach_item(MODULE_GPIO, &gpio_handle);
202 } else {
203 duk_push_pointer(ctx, (void *)gpio_handle.handle);
204 }
205 return 1;
206 }
207
native_ir_close(duk_context * ctx)208 static duk_ret_t native_ir_close(duk_context *ctx)
209 {
210 int8_t result = -1;
211 item_handle_t gpio_handle;
212 gpio_dev_t *gpio_device = NULL;
213
214 if (!duk_is_pointer(ctx, 0)) {
215 amp_warn(MOD_STR, "parameter must be handle");
216 goto out;
217 }
218 gpio_handle.handle = duk_get_pointer(ctx, 0);
219 gpio_device = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
220 if (NULL == gpio_device) {
221 amp_error(MOD_STR, "board_get_node_by_handle fail!\n");
222 goto out;
223 }
224 aos_hal_gpio_disable_irq(gpio_device);
225 gpio_device->priv = NULL;
226 board_disattach_item(MODULE_GPIO, &gpio_handle);
227 result = 0;
228 out:
229 duk_push_int(ctx, result);
230 return 1;
231 }
232
233 struct gpio_irq_notify_param {
234 int js_cb_ref;
235 int value;
236 };
237
gpio_irq_notify(void * arg)238 static void gpio_irq_notify(void *arg)
239 {
240 struct gpio_irq_notify_param *p = (struct gpio_irq_notify_param *)arg;
241 amp_debug(MOD_STR, "value: 0x%x\n", p->value);
242 duk_context *ctx = be_get_context();
243 be_push_ref(ctx, p->js_cb_ref);
244 duk_push_int(ctx, p->value);
245 if (duk_pcall(ctx, 1) != DUK_EXEC_SUCCESS) {
246 amp_console("%s", duk_safe_to_stacktrace(ctx, -1));
247 }
248 duk_pop(ctx);
249 aos_free(p);
250
251 duk_gc(ctx, 0);
252 }
253
254 /* avoid stdout in irq function */
ir_handle(void * arg)255 static void ir_handle(void *arg)
256 {
257 uint32_t value = 0;
258 gpio_dev_t *gpio = (gpio_dev_t *)arg;
259
260 if (NULL == gpio) {
261 /* amp_error(MOD_STR, "param error!\n"); */
262 return;
263 }
264 value = ir_nec(gpio);
265 if (0x00 == value) {
266 return;
267 }
268
269 int js_cb_ref = (int)gpio->priv;
270 if (js_cb_ref <= 0) {
271 /* amp_error(MOD_STR, "js cb ref error, ref: %d\n", js_cb_ref); */
272 return;
273 }
274
275 struct gpio_irq_notify_param *p =
276 (struct gpio_irq_notify_param *)aos_malloc(sizeof(*p));
277 p->js_cb_ref = js_cb_ref;
278 p->value = value & 0xFFFF;
279 if (amp_task_schedule_call(gpio_irq_notify, p) < 0) {
280 /* amp_warn(MOD_STR, "amp_task_schedule_call failed\n"); */
281 aos_free(p);
282 }
283 }
284
native_ir_on(duk_context * ctx)285 static duk_ret_t native_ir_on(duk_context *ctx)
286 {
287 int8_t ret = -1;
288 item_handle_t gpio_handle;
289 gpio_handle.handle = NULL;
290 gpio_dev_t *gpio_device = NULL;
291
292 if (!duk_is_pointer(ctx, 0) || !duk_is_function(ctx, 1)) {
293 amp_warn(MOD_STR, "parameter must be handle and function");
294 goto out;
295 }
296 gpio_handle.handle = duk_get_pointer(ctx, 0);
297 gpio_device = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
298 if (NULL == gpio_device) {
299 amp_error(MOD_STR, "board_get_node_by_handle fail!\n");
300 goto out;
301 }
302 ret = aos_hal_gpio_enable_irq(gpio_device, IRQ_TRIGGER_FALLING_EDGE, ir_handle,
303 gpio_device);
304 if (ret < 0) {
305 amp_error(MOD_STR, "aos_hal_gpio_enable_irq fail!\n");
306 goto out;
307 }
308 duk_dup(ctx, 1);
309 int js_cb_ref = be_ref(ctx);
310 gpio_device->priv = (void *)js_cb_ref;
311 out:
312 duk_push_int(ctx, ret);
313 return 1;
314 }
315
ir_delay(uint32_t counts)316 static void ir_delay(uint32_t counts)
317 {
318 uint32_t i = 0;
319 for (i = 0; i < counts; i++) jse_osal_delay10us();
320 }
321
ir_byte(gpio_dev_t * sda,gpio_dev_t * scl,unsigned char bData)322 static void ir_byte(gpio_dev_t *sda, gpio_dev_t *scl, unsigned char bData)
323 {
324 int8_t i = 0;
325 uint32_t val = 0;
326 aos_hal_gpio_output_low(scl);
327 ir_delay(4);
328 for (i = 7; i >= 0; i--) {
329 ir_delay(4);
330 if ((bData >> i) & 0x01) {
331 aos_hal_gpio_output_high(sda);
332 } else {
333 aos_hal_gpio_output_low(sda);
334 }
335 ir_delay(4);
336 aos_hal_gpio_output_high(scl);
337 ir_delay(4);
338 aos_hal_gpio_output_low(scl);
339 }
340 aos_hal_gpio_output_high(sda);
341 ir_delay(16);
342 aos_hal_gpio_output_high(scl);
343 ir_delay(16);
344 aos_hal_gpio_input_get(sda, &val);
345 ir_delay(16);
346 aos_hal_gpio_output_low(scl);
347 ir_delay(16);
348 }
349
ir_buff(gpio_dev_t * sda,gpio_dev_t * scl,uint8_t * data,uint32_t count)350 static void ir_buff(gpio_dev_t *sda, gpio_dev_t *scl, uint8_t *data,
351 uint32_t count)
352 {
353 uint32_t i = 0;
354 aos_hal_gpio_output_high(sda);
355 aos_hal_gpio_output_high(scl);
356 ir_delay(4);
357 aos_hal_gpio_output_low(scl);
358 ir_delay(8);
359 aos_hal_gpio_output_high(scl);
360 jse_osal_delay(20);
361 aos_hal_gpio_output_high(scl);
362 aos_hal_gpio_output_high(sda);
363 ir_delay(8);
364 aos_hal_gpio_output_low(sda);
365 ir_delay(40);
366 aos_hal_gpio_output_low(scl);
367 ir_delay(8);
368 ir_delay(4);
369 for (i = 0; i < count; i++) {
370 ir_byte(sda, scl, data[i]);
371 ir_delay(4);
372 }
373 ir_delay(4);
374 aos_hal_gpio_output_low(scl);
375 aos_hal_gpio_output_low(sda);
376 ir_delay(4);
377 aos_hal_gpio_output_high(scl);
378 ir_delay(4);
379 aos_hal_gpio_output_high(sda);
380 ir_delay(8);
381 aos_hal_gpio_output_low(sda);
382 aos_hal_gpio_output_low(scl);
383 ir_delay(4);
384 aos_hal_gpio_output_high(scl);
385 ir_delay(4);
386 aos_hal_gpio_output_high(sda);
387 ir_delay(8);
388 }
389
native_ir_send(duk_context * ctx)390 static duk_ret_t native_ir_send(duk_context *ctx)
391 {
392 uint8_t *data = NULL;
393 uint32_t len = 0;
394 uint32_t i = 0;
395 item_handle_t gpio_handle;
396 gpio_dev_t *gpio_scl = NULL;
397 gpio_dev_t *gpio_sda = NULL;
398 int arr_idx;
399 int err = -1;
400
401 if (!duk_is_pointer(ctx, 0) || !duk_is_pointer(ctx, 1) ||
402 !duk_is_array(ctx, 2)) {
403 amp_warn(MOD_STR, "parameter must be handle, handle and array");
404 goto out;
405 }
406
407 gpio_handle.handle = duk_get_pointer(ctx, 0);
408 gpio_sda = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
409 if (NULL == gpio_sda) {
410 amp_error(MOD_STR, "board_get_node_by_handle fail!\n");
411 goto out;
412 }
413
414 gpio_handle.handle = duk_get_pointer(ctx, 1);
415 gpio_scl = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
416 if (NULL == gpio_scl) {
417 amp_error(MOD_STR, "board_get_node_by_handle fail!\n");
418 goto out;
419 }
420
421 arr_idx = duk_normalize_index(ctx, 2);
422 len = duk_get_length(ctx, arr_idx);
423 data = (uint8_t *)aos_malloc(sizeof(uint8_t) * len);
424 if (NULL == data) {
425 amp_warn(MOD_STR, "allocate memory failed");
426 goto out;
427 }
428 for (i = 0; i < len; i++) {
429 duk_get_prop_index(ctx, arr_idx, i);
430 if (!duk_is_number(ctx, -1)) {
431 amp_warn(MOD_STR, "data is not number, index: %d", i);
432 duk_pop(ctx);
433 goto out;
434 }
435 data[i] = (uint8_t)duk_get_int(ctx, -1);
436 duk_pop(ctx);
437 }
438 ir_buff(gpio_sda, gpio_scl, data, len);
439 ir_delay(10);
440 ir_buff(gpio_sda, gpio_scl, data, len);
441 ir_delay(10);
442 /* ir_buff(gpio_sda,gpio_scl,data,len); */
443 err = 0;
444 out:
445 aos_free(data);
446 duk_push_int(ctx, err);
447 return 1;
448 }
449
native_ir_learn(duk_context * ctx)450 static duk_ret_t native_ir_learn(duk_context *ctx)
451 {
452 uint32_t i = 0;
453 int32_t ret = -1;
454 uint8_t buff[232] = {0x00};
455 item_handle_t gpio_handle;
456 gpio_dev_t *gpio_scl = NULL;
457 gpio_dev_t *gpio_sda = NULL;
458 gpio_dev_t *gpio_busy = NULL;
459
460 if (!duk_is_pointer(ctx, 0) || !duk_is_pointer(ctx, 1) ||
461 !duk_is_pointer(ctx, 2)) {
462 amp_warn(MOD_STR, "parameter must be handle, handle and handle");
463 goto failed;
464 }
465
466 gpio_handle.handle = duk_get_pointer(ctx, 0);
467 gpio_sda = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
468 if (NULL == gpio_sda) {
469 amp_error(MOD_STR, "board_get_node_by_handle fail!\n");
470 goto failed;
471 }
472
473 gpio_handle.handle = duk_get_pointer(ctx, 1);
474 gpio_scl = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
475 if (NULL == gpio_scl) {
476 amp_error(MOD_STR, "board_get_node_by_handle fail!\n");
477 goto failed;
478 }
479
480 gpio_handle.handle = duk_get_pointer(ctx, 2);
481 gpio_busy = board_get_node_by_handle(MODULE_GPIO, &gpio_handle);
482 if (NULL == gpio_busy) {
483 amp_error(MOD_STR, "board_get_node_by_handle fail!\n");
484 goto failed;
485 }
486
487 ret = ir_learn_start(gpio_scl->port, gpio_sda->port, gpio_busy->port, buff);
488 if (ret <= 0) {
489 amp_error(MOD_STR, "ir_learn_start fail!\n");
490 goto failed;
491 }
492 int arr_idx = duk_push_array(ctx);
493 for (i = 0; i < 232; ++i) {
494 duk_push_int(ctx, buff[i]);
495 duk_put_prop_index(ctx, arr_idx, i);
496 }
497 return 1;
498
499 failed:
500 duk_push_null(ctx);
501 return 1;
502 }
503
module_ir_register(void)504 void module_ir_register(void)
505 {
506 duk_context *ctx = be_get_context();
507
508 duk_push_object(ctx);
509
510 AMP_ADD_FUNCTION("open", native_ir_open, 1);
511 AMP_ADD_FUNCTION("on", native_ir_on, 2);
512 AMP_ADD_FUNCTION("send", native_ir_send, 3);
513 AMP_ADD_FUNCTION("learn", native_ir_learn, 3);
514 AMP_ADD_FUNCTION("close", native_ir_close, 1);
515
516 duk_put_prop_string(ctx, -2, "IR");
517 }
518