LibDriver IR_REMOTE
Loading...
Searching...
No Matches
driver_ir_remote.c
Go to the documentation of this file.
1
36
37#include "driver_ir_remote.h"
38#include <stdlib.h>
39
43#define CHIP_NAME "NEC IR REMOTE"
44#define MANUFACTURER_NAME "NEC"
45#define SUPPLY_VOLTAGE_MIN 2.7f
46#define SUPPLY_VOLTAGE_MAX 5.5f
47#define MAX_CURRENT 1.5f
48#define TEMPERATURE_MIN -40.0f
49#define TEMPERATURE_MAX 125.0f
50#define DRIVER_VERSION 1000
51
55#define IR_REMOTE_CHECK_START_HIGH 9000
56#define IR_REMOTE_CHECK_START_LOW 4500
57#define IR_REMOTE_CHECK_DATA0_HIGH 560
58#define IR_REMOTE_CHECK_DATA0_LOW 560
59#define IR_REMOTE_CHECK_DATA1_HIGH 560
60#define IR_REMOTE_CHECK_DATA1_LOW 1680
61#define IR_REMOTE_CHECK_DATA_0_1_EDGE 1000
62#define IR_REMOTE_CHECK_STOP 560
63#define IR_REMOTE_CHECK_REPEAT 2250
64
74static inline uint8_t a_check_frame(uint16_t check, uint16_t t)
75{
76 if (abs((int)check - (int)t) > (int)((float)(t) * IR_REMOTE_MAX_RANGE)) /* check the time */
77 {
78 return 1; /* check failed */
79 }
80 else
81 {
82 return 0; /* success return 0 */
83 }
84}
85
91static void a_ir_remote_nec_repeat_decode(ir_remote_handle_t *handle)
92{
93 uint16_t i;
94 uint16_t len;
95 ir_remote_t data;
96
97 len = handle->decode_len - 1; /* len - 1 */
98 for (i = 0; i < len; i++) /* diff all time */
99 {
100 int64_t diff;
101
102 diff = (int64_t)((int64_t)handle->decode[i + 1].t.s -
103 (int64_t)handle->decode[i].t.s) * 1000000 +
104 (int64_t)((int64_t)handle->decode[i + 1].t.us -
105 (int64_t)handle->decode[i].t.us); /* diff time */
106 handle->decode[i].diff_us = (uint32_t)diff; /* save the time diff */
107 }
108
109 if (a_check_frame(handle->decode[0].diff_us, IR_REMOTE_CHECK_START_HIGH) != 0) /* check start diff */
110 {
111 if (handle->receive_callback != NULL) /* check the receive callback */
112 {
113 data.address = 0x00; /* set address 0x00 */
114 data.command = 0x00; /* set command 0x00 */
115 data.status = IR_REMOTE_STATUS_FRAME_INVALID; /* frame invalid */
116 handle->receive_callback(&data); /* run the callback */
117 }
118
119 return; /* return */
120 }
121 if (a_check_frame(handle->decode[1].diff_us, IR_REMOTE_CHECK_REPEAT) != 0) /* check repeat */
122 {
123 if (handle->receive_callback != NULL) /* check the receive callback */
124 {
125 data.address = 0x00; /* set address 0x00 */
126 data.command = 0x00; /* set command 0x00 */
127 data.status = IR_REMOTE_STATUS_FRAME_INVALID; /* frame invalid */
128 handle->receive_callback(&data); /* run the callback */
129 }
130
131 return; /* return */
132 }
133 if (a_check_frame(handle->decode[2].diff_us, IR_REMOTE_CHECK_STOP) != 0) /* check stop */
134 {
135 if (handle->receive_callback != NULL) /* check the receive callback */
136 {
137 data.address = 0x00; /* set address 0x00 */
138 data.command = 0x00; /* set command 0x00 */
139 data.status = IR_REMOTE_STATUS_FRAME_INVALID; /* frame invalid */
140 handle->receive_callback(&data); /* run the callback */
141 }
142
143 return; /* return */
144 }
145
146 if (handle->receive_callback != NULL) /* check the receive callback */
147 {
148 data.address = handle->last_code.address; /* set address 0x00 */
149 data.command = handle->last_code.command; /* set command 0x00 */
150 data.status = IR_REMOTE_STATUS_REPEAT; /* frame invalid */
151 handle->receive_callback(&data); /* run the callback */
152 }
153 handle->decode_len = 0; /* in order to trigger repeat decoding for the next four edges */
154}
155
161static void a_ir_remote_nec_decode(ir_remote_handle_t *handle)
162{
163 uint8_t tmp;
164 uint8_t tmp_r;
165 uint8_t tmp_cmp;
166 uint16_t i;
167 uint16_t len;
168 ir_remote_t data;
169
170 len = handle->decode_len - 1; /* len - 1 */
171 for (i = 0; i < len; i++) /* diff all time */
172 {
173 int64_t diff;
174
175 diff = (int64_t)((int64_t)handle->decode[i + 1].t.s -
176 (int64_t)handle->decode[i].t.s) * 1000000 +
177 (int64_t)((int64_t)handle->decode[i + 1].t.us -
178 (int64_t)handle->decode[i].t.us); /* diff time */
179 handle->decode[i].diff_us = (uint32_t)diff; /* save the time diff */
180 }
181
182 if (a_check_frame(handle->decode[0].diff_us, IR_REMOTE_CHECK_START_HIGH) != 0) /* check start diff */
183 {
184 if (handle->receive_callback != NULL) /* check the receive callback */
185 {
186 data.address = 0x00; /* set address 0x00 */
187 data.command = 0x00; /* set command 0x00 */
188 data.status = IR_REMOTE_STATUS_FRAME_INVALID; /* frame invalid */
189 handle->receive_callback(&data); /* run the callback */
190 }
191
192 return; /* return */
193 }
194 if (a_check_frame(handle->decode[1].diff_us, IR_REMOTE_CHECK_START_LOW) != 0) /* check start low */
195 {
196 if (handle->receive_callback != NULL) /* check the receive callback */
197 {
198 data.address = 0x00; /* set address 0x00 */
199 data.command = 0x00; /* set command 0x00 */
200 data.status = IR_REMOTE_STATUS_FRAME_INVALID; /* frame invalid */
201 handle->receive_callback(&data); /* run the callback */
202 }
203
204 return; /* return */
205 }
206
207 tmp = 0; /* init 0 */
208 for (i = 0; i < 8; i++) /* parse 8 bit */
209 {
210 if (a_check_frame(handle->decode[2 + i * 2 + 0].diff_us, IR_REMOTE_CHECK_DATA1_HIGH) != 0) /* check data high */
211 {
212 if (handle->receive_callback != NULL) /* check the receive callback */
213 {
214 data.address = 0x00; /* set address 0x00 */
215 data.command = 0x00; /* set command 0x00 */
216 data.status = IR_REMOTE_STATUS_ADDR_ERR; /* address error */
217 handle->receive_callback(&data); /* run the callback */
218 }
219
220 return; /* return */
221 }
222 if (handle->decode[2 + i * 2 + 1].diff_us > IR_REMOTE_CHECK_DATA_0_1_EDGE) /* check data0 and data1 */
223 {
224 if (a_check_frame(handle->decode[2 + i * 2 + 1].diff_us, IR_REMOTE_CHECK_DATA1_LOW) != 0) /* check data 1 */
225 {
226 data.address = 0x00; /* set address 0x00 */
227 data.command = 0x00; /* set command 0x00 */
228 data.status = IR_REMOTE_STATUS_ADDR_ERR; /* address error */
229 if (handle->receive_callback != NULL) /* check the receive callback */
230 {
231 handle->receive_callback(&data); /* run the callback */
232 }
233
234 return; /* return */
235 }
236 tmp |= 1 << i; /* set bit */
237 }
238 else /* check data 0 */
239 {
240 if (a_check_frame(handle->decode[2 + i * 2 + 1].diff_us, IR_REMOTE_CHECK_DATA0_LOW) != 0) /* check data 0 */
241 {
242 data.address = 0x00; /* set address 0x00 */
243 data.command = 0x00; /* set command 0x00 */
244 data.status = IR_REMOTE_STATUS_ADDR_ERR; /* address error */
245 if (handle->receive_callback != NULL) /* check the receive callback */
246 {
247 handle->receive_callback(&data); /* run the callback */
248 }
249
250 return; /* return */
251 }
252 tmp |= 0 << i; /* set bit */
253 }
254 }
255 tmp_r = 0; /* init 0 */
256 for (i = 0; i < 8; i++) /* parse 8 bit */
257 {
258 if (a_check_frame(handle->decode[18 + i * 2 + 0].diff_us, IR_REMOTE_CHECK_DATA1_HIGH) != 0) /* check data high */
259 {
260 if (handle->receive_callback != NULL) /* check the receive callback */
261 {
262 data.address = 0x00; /* set address 0x00 */
263 data.command = 0x00; /* set command 0x00 */
264 data.status = IR_REMOTE_STATUS_ADDR_ERR; /* address error */
265 handle->receive_callback(&data); /* run the callback */
266 }
267
268 return; /* return */
269 }
270 if (handle->decode[18 + i * 2 + 1].diff_us > IR_REMOTE_CHECK_DATA_0_1_EDGE) /* check data0 and data1 */
271 {
272 if (a_check_frame(handle->decode[18 + i * 2 + 1].diff_us, IR_REMOTE_CHECK_DATA1_LOW) != 0) /* check data 1 */
273 {
274 data.address = 0x00; /* set address 0x00 */
275 data.command = 0x00; /* set command 0x00 */
276 data.status = IR_REMOTE_STATUS_ADDR_ERR; /* address error */
277 if (handle->receive_callback != NULL) /* check the receive callback */
278 {
279 handle->receive_callback(&data); /* run the callback */
280 }
281
282 return; /* return */
283 }
284 tmp_r |= 1 << i; /* set bit */
285 }
286 else /* check data 0 */
287 {
288 if (a_check_frame(handle->decode[18 + i * 2 + 1].diff_us, IR_REMOTE_CHECK_DATA0_LOW) != 0) /* check data 0 */
289 {
290 data.address = 0x00; /* set address 0x00 */
291 data.command = 0x00; /* set command 0x00 */
292 data.status = IR_REMOTE_STATUS_ADDR_ERR; /* address error */
293 if (handle->receive_callback != NULL) /* check the receive callback */
294 {
295 handle->receive_callback(&data); /* run the callback */
296 }
297
298 return; /* return */
299 }
300 tmp_r |= 0 << i; /* set bit */
301 }
302 }
303 tmp_cmp = ~tmp_r; /* get the check value */
304 if (tmp != tmp_cmp) /* check the value */
305 {
306 data.address = 0x00; /* set address 0x00 */
307 data.command = 0x00; /* set command 0x00 */
308 data.status = IR_REMOTE_STATUS_ADDR_ERR; /* address error */
309 if (handle->receive_callback != NULL) /* check the receive callback */
310 {
311 handle->receive_callback(&data); /* run the callback */
312 }
313
314 return; /* return */
315 }
316 data.address = tmp; /* set the address */
317
318 tmp = 0; /* init 0 */
319 for (i = 0; i < 8; i++) /* parse 8 bit */
320 {
321 if (a_check_frame(handle->decode[34 + i * 2 + 0].diff_us, IR_REMOTE_CHECK_DATA1_HIGH) != 0) /* check data high */
322 {
323 if (handle->receive_callback != NULL) /* check the receive callback */
324 {
325 data.command = 0x00; /* set command 0x00 */
326 data.status = IR_REMOTE_STATUS_CMD_ERR; /* command error */
327 handle->receive_callback(&data); /* run the callback */
328 }
329
330 return; /* return */
331 }
332 if (handle->decode[34 + i * 2 + 1].diff_us > IR_REMOTE_CHECK_DATA_0_1_EDGE) /* check data0 and data1 */
333 {
334 if (a_check_frame(handle->decode[34 + i * 2 + 1].diff_us, IR_REMOTE_CHECK_DATA1_LOW) != 0) /* check data 1 */
335 {
336 data.command = 0x00; /* set command 0x00 */
337 data.status = IR_REMOTE_STATUS_CMD_ERR; /* command error */
338 if (handle->receive_callback != NULL) /* check the receive callback */
339 {
340 handle->receive_callback(&data); /* run the callback */
341 }
342
343 return; /* return */
344 }
345 tmp |= 1 << i; /* set bit */
346 }
347 else /* check data 0 */
348 {
349 if (a_check_frame(handle->decode[34 + i * 2 + 1].diff_us, IR_REMOTE_CHECK_DATA0_LOW) != 0) /* check data 0 */
350 {
351 data.command = 0x00; /* set command 0x00 */
352 data.status = IR_REMOTE_STATUS_CMD_ERR; /* command error */
353 if (handle->receive_callback != NULL) /* check the receive callback */
354 {
355 handle->receive_callback(&data); /* run the callback */
356 }
357
358 return; /* return */
359 }
360 tmp |= 0 << i; /* set bit */
361 }
362 }
363 tmp_r = 0; /* init 0 */
364 for (i = 0; i < 8; i++) /* parse 8 bit */
365 {
366 if (a_check_frame(handle->decode[50 + i * 2 + 0].diff_us, IR_REMOTE_CHECK_DATA1_HIGH) != 0) /* check data high */
367 {
368 if (handle->receive_callback != NULL) /* check the receive callback */
369 {
370 data.command = 0x00; /* set command 0x00 */
371 data.status = IR_REMOTE_STATUS_CMD_ERR; /* command error */
372 handle->receive_callback(&data); /* run the callback */
373 }
374
375 return; /* return */
376 }
377 if (handle->decode[50 + i * 2 + 1].diff_us > IR_REMOTE_CHECK_DATA_0_1_EDGE) /* check data0 and data1 */
378 {
379 if (a_check_frame(handle->decode[50 + i * 2 + 1].diff_us, IR_REMOTE_CHECK_DATA1_LOW) != 0) /* check data 1 */
380 {
381 data.command = 0x00; /* set command 0x00 */
382 data.status = IR_REMOTE_STATUS_CMD_ERR; /* command error */
383 if (handle->receive_callback != NULL) /* check the receive callback */
384 {
385 handle->receive_callback(&data); /* run the callback */
386 }
387
388 return; /* return */
389 }
390 tmp_r |= 1 << i; /* set bit */
391 }
392 else /* check data 0 */
393 {
394 if (a_check_frame(handle->decode[50 + i * 2 + 1].diff_us, IR_REMOTE_CHECK_DATA0_LOW) != 0) /* check data 0 */
395 {
396 data.command = 0x00; /* set command 0x00 */
397 data.status = IR_REMOTE_STATUS_CMD_ERR; /* command error */
398 if (handle->receive_callback != NULL) /* check the receive callback */
399 {
400 handle->receive_callback(&data); /* run the callback */
401 }
402
403 return; /* return */
404 }
405 tmp_r |= 0 << i; /* set bit */
406 }
407 }
408 tmp_cmp = ~tmp_r; /* get the check value */
409 if (tmp != tmp_cmp) /* check the value */
410 {
411 data.command = 0x00; /* set command 0x00 */
412 data.status = IR_REMOTE_STATUS_CMD_ERR; /* command error */
413 if (handle->receive_callback != NULL) /* check the receive callback */
414 {
415 handle->receive_callback(&data); /* run the callback */
416 }
417
418 return; /* return */
419 }
420 data.command = tmp; /* set the command */
421
422 if (a_check_frame(handle->decode[66].diff_us, IR_REMOTE_CHECK_STOP) != 0) /* check stop frame */
423 {
424 if (handle->receive_callback != NULL) /* check the receive callback */
425 {
426 data.status = IR_REMOTE_STATUS_FRAME_INVALID; /* frame invalid */
427 handle->receive_callback(&data); /* run the callback */
428 }
429
430 return; /* return */
431 }
432
433 if (handle->receive_callback != NULL) /* check the receive callback */
434 {
435 data.status = IR_REMOTE_STATUS_OK; /* frame ok */
436 handle->receive_callback(&data); /* run the callback */
437 }
438 handle->last_code.address = data.address; /* save address */
439 handle->last_code.command = data.command; /* save command */
440 handle->last_code.status = data.status; /* save status */
441 handle->decode_len = 0; /* clear the buffer */
442}
443
455{
456 uint8_t res;
457 int64_t diff;
459
460 if (handle == NULL) /* check handle */
461 {
462 return 2; /* return error */
463 }
464 if (handle->inited != 1) /* check handle initialization */
465 {
466 return 3; /* return error */
467 }
468
469 res = handle->timestamp_read(&t); /* timestamp read */
470 if (res != 0) /* check result */
471 {
472 handle->debug_print("ir_remote: timestamp read failed.\n"); /* timestamp read failed */
473
474 return 1; /* return error */
475 }
476 diff = (int64_t)((int64_t)t.s -
477 (int64_t)handle->last_time.s) * 1000000 +
478 (int64_t)((int64_t)t.us - (int64_t)handle->last_time.us); /* now - last time */
479 if (diff - (int64_t)200000L >= 0) /* if over 1s, force reset */
480 {
481 handle->decode_len = 0; /* reset the decode */
482 }
483 if (handle->decode_len >= 127) /* check the max length */
484 {
485 handle->decode_len = 0; /* reset the decode */
486 }
487 handle->decode[handle->decode_len].t.s = t.s; /* save s */
488 handle->decode[handle->decode_len].t.us = t.us; /* save us */
489 handle->decode_len++; /* length++ */
490 handle->last_time.s = t.s; /* save last time */
491 handle->last_time.us = t.us; /* save last time */
492 if (handle->decode_len >= 68) /* check the end length */
493 {
494 diff = (int64_t)((int64_t)handle->decode[2].t.s -
495 (int64_t)handle->decode[1].t.s) * 1000000 +
496 (int64_t)((int64_t)handle->decode[2].t.us -
497 (int64_t)handle->decode[1].t.us); /* diff time */
498 if (a_check_frame((uint16_t)diff, IR_REMOTE_CHECK_START_LOW) == 0) /* check the frame */
499 {
500 a_ir_remote_nec_decode(handle); /* try to decode */
501 }
502 }
503 if (handle->decode_len == 4) /* check the end length */
504 {
505 diff = (int64_t)((int64_t)handle->decode[2].t.s -
506 (int64_t)handle->decode[1].t.s) * 1000000 +
507 (int64_t)((int64_t)handle->decode[2].t.us -
508 (int64_t)handle->decode[1].t.us); /* diff time */
509 if (a_check_frame((uint16_t)diff, IR_REMOTE_CHECK_REPEAT) == 0) /* check the frame */
510 {
511 a_ir_remote_nec_repeat_decode(handle); /* try to decode */
512 }
513 }
514
515 return 0; /* success return 0 */
516}
517
529{
530 uint8_t res;
532
533 if (handle == NULL) /* check handle */
534 {
535 return 2; /* return error */
536 }
537 if (handle->debug_print == NULL) /* check debug_print */
538 {
539 return 3; /* return error */
540 }
541 if (handle->timestamp_read == NULL) /* check timestamp_read */
542 {
543 handle->debug_print("ir_remote: timestamp_read is null.\n"); /* timestamp_read is null */
544
545 return 3; /* return error */
546 }
547 if (handle->delay_ms == NULL) /* check delay_ms */
548 {
549 handle->debug_print("ir_remote: delay_ms is null.\n"); /* delay_ms is null */
550
551 return 3; /* return error */
552 }
553 if (handle->receive_callback == NULL) /* check receive_callback */
554 {
555 handle->debug_print("ir_remote: receive_callback is null.\n"); /* receive_callback is null */
556
557 return 3; /* return error */
558 }
559
560 res = handle->timestamp_read(&t); /* timestamp read */
561 if (res != 0) /* check result */
562 {
563 handle->debug_print("ir_remote: timestamp read failed.\n"); /* timestamp read failed */
564
565 return 1; /* return error */
566 }
567 handle->last_time.s = t.s; /* save last time */
568 handle->last_time.us = t.us; /* save last time */
569 handle->last_code.address = 0x00; /* init address 0 */
570 handle->last_code.command = 0x00; /* init command 0 */
571 handle->last_code.status = 0x00; /* init status 0 */
572 handle->decode_len = 0; /* init 0 */
573 handle->inited = 1; /* flag inited */
574
575 return 0; /* success return 0 */
576}
577
588{
589 if (handle == NULL) /* check handle */
590 {
591 return 2; /* return error */
592 }
593 if (handle->inited != 1) /* check handle initialization */
594 {
595 return 3; /* return error */
596 }
597
598 handle->inited = 0; /* flag close */
599
600 return 0; /* success return 0 */
601}
602
612{
613 if (info == NULL) /* check handle */
614 {
615 return 2; /* return error */
616 }
617
618 memset(info, 0, sizeof(ir_remote_info_t)); /* initialize ir_remote info structure */
619 strncpy(info->chip_name, CHIP_NAME, 32); /* copy chip name */
620 strncpy(info->manufacturer_name, MANUFACTURER_NAME, 32); /* copy manufacturer name */
621 strncpy(info->interface, "GPIO", 8); /* copy interface name */
622 info->supply_voltage_min_v = SUPPLY_VOLTAGE_MIN; /* set minimal supply voltage */
623 info->supply_voltage_max_v = SUPPLY_VOLTAGE_MAX; /* set maximum supply voltage */
624 info->max_current_ma = MAX_CURRENT; /* set maximum current */
625 info->temperature_max = TEMPERATURE_MAX; /* set minimal temperature */
626 info->temperature_min = TEMPERATURE_MIN; /* set maximum temperature */
627 info->driver_version = DRIVER_VERSION; /* set driver version */
628
629 return 0; /* success return 0 */
630}
#define IR_REMOTE_CHECK_DATA1_HIGH
#define MAX_CURRENT
#define IR_REMOTE_CHECK_START_LOW
#define IR_REMOTE_CHECK_DATA_0_1_EDGE
#define SUPPLY_VOLTAGE_MAX
#define IR_REMOTE_CHECK_DATA1_LOW
#define TEMPERATURE_MAX
#define MANUFACTURER_NAME
#define TEMPERATURE_MIN
#define SUPPLY_VOLTAGE_MIN
#define IR_REMOTE_CHECK_START_HIGH
frame check definition
#define IR_REMOTE_CHECK_STOP
#define IR_REMOTE_CHECK_REPEAT
#define CHIP_NAME
chip information definition
#define DRIVER_VERSION
#define IR_REMOTE_CHECK_DATA0_LOW
driver ir remote header file
#define IR_REMOTE_MAX_RANGE
ir_remote max range definition
uint8_t ir_remote_irq_handler(ir_remote_handle_t *handle)
irq handler
uint8_t ir_remote_init(ir_remote_handle_t *handle)
initialize the chip
uint8_t ir_remote_info(ir_remote_info_t *info)
get chip's information
struct ir_remote_info_s ir_remote_info_t
ir_remote information structure definition
struct ir_remote_handle_s ir_remote_handle_t
ir_remote handle structure definition
uint8_t ir_remote_deinit(ir_remote_handle_t *handle)
close the chip
struct ir_remote_time_s ir_remote_time_t
ir_remote time structure definition
struct ir_remote_s ir_remote_t
ir_remote structure definition
@ IR_REMOTE_STATUS_REPEAT
@ IR_REMOTE_STATUS_OK
@ IR_REMOTE_STATUS_FRAME_INVALID
@ IR_REMOTE_STATUS_CMD_ERR
@ IR_REMOTE_STATUS_ADDR_ERR
ir_remote_time_t t
ir_remote_decode_t decode[128]
void(* delay_ms)(uint32_t ms)
void(* debug_print)(const char *const fmt,...)
uint8_t(* timestamp_read)(ir_remote_time_t *t)
void(* receive_callback)(ir_remote_t *data)
ir_remote_time_t last_time