source: rtos_arduino/trunk/arduino_lib/libraries/RobotIRremote/src/IRremote.cpp@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 21.1 KB
Line 
1/*
2 * IRremote
3 * Version 0.11 August, 2009
4 * Copyright 2009 Ken Shirriff
5 * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
6 *
7 * Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
8 * Modified by Mitra Ardron <mitra@mitra.biz>
9 * Added Sanyo and Mitsubishi controllers
10 * Modified Sony to spot the repeat codes that some Sony's send
11 *
12 * Interrupt code based on NECIRrcv by Joe Knapp
13 * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
14 * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
15 *
16 * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
17 */
18
19#include "IRremote.h"
20#include "IRremoteInt.h"
21
22// Provides ISR
23#include <avr/interrupt.h>
24
25volatile irparams_t irparams;
26
27// These versions of MATCH, MATCH_MARK, and MATCH_SPACE are only for debugging.
28// To use them, set DEBUG in IRremoteInt.h
29// Normally macros are used for efficiency
30#ifdef DEBUG
31int MATCH(int measured, int desired) {
32 Serial.print("Testing: ");
33 Serial.print(TICKS_LOW(desired), DEC);
34 Serial.print(" <= ");
35 Serial.print(measured, DEC);
36 Serial.print(" <= ");
37 Serial.println(TICKS_HIGH(desired), DEC);
38 return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);
39}
40
41int MATCH_MARK(int measured_ticks, int desired_us) {
42 Serial.print("Testing mark ");
43 Serial.print(measured_ticks * USECPERTICK, DEC);
44 Serial.print(" vs ");
45 Serial.print(desired_us, DEC);
46 Serial.print(": ");
47 Serial.print(TICKS_LOW(desired_us + MARK_EXCESS), DEC);
48 Serial.print(" <= ");
49 Serial.print(measured_ticks, DEC);
50 Serial.print(" <= ");
51 Serial.println(TICKS_HIGH(desired_us + MARK_EXCESS), DEC);
52 return measured_ticks >= TICKS_LOW(desired_us + MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS);
53}
54
55int MATCH_SPACE(int measured_ticks, int desired_us) {
56 Serial.print("Testing space ");
57 Serial.print(measured_ticks * USECPERTICK, DEC);
58 Serial.print(" vs ");
59 Serial.print(desired_us, DEC);
60 Serial.print(": ");
61 Serial.print(TICKS_LOW(desired_us - MARK_EXCESS), DEC);
62 Serial.print(" <= ");
63 Serial.print(measured_ticks, DEC);
64 Serial.print(" <= ");
65 Serial.println(TICKS_HIGH(desired_us - MARK_EXCESS), DEC);
66 return measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS);
67}
68#else
69int MATCH(int measured, int desired) {return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);}
70int MATCH_MARK(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us + MARK_EXCESS));}
71int MATCH_SPACE(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us - MARK_EXCESS));}
72#endif
73
74IRrecv::IRrecv(int recvpin)
75{
76 irparams.recvpin = recvpin;
77 irparams.blinkflag = 0;
78}
79
80// initialization
81void IRrecv::enableIRIn() {
82 cli();
83 // setup pulse clock timer interrupt
84 //Prescale /8 (16M/8 = 0.5 microseconds per tick)
85 // Therefore, the timer interval can range from 0.5 to 128 microseconds
86 // depending on the reset value (255 to 0)
87 TIMER_CONFIG_NORMAL();
88
89 //Timer2 Overflow Interrupt Enable
90 TIMER_ENABLE_INTR;
91
92 TIMER_RESET;
93
94 sei(); // enable interrupts
95
96 // initialize state machine variables
97 irparams.rcvstate = STATE_IDLE;
98 irparams.rawlen = 0;
99
100 // set pin modes
101 pinMode(irparams.recvpin, INPUT);
102}
103
104// enable/disable blinking of pin 13 on IR processing
105void IRrecv::blink13(int blinkflag)
106{
107 irparams.blinkflag = blinkflag;
108 if (blinkflag)
109 pinMode(BLINKLED, OUTPUT);
110}
111
112// TIMER2 interrupt code to collect raw data.
113// Widths of alternating SPACE, MARK are recorded in rawbuf.
114// Recorded in ticks of 50 microseconds.
115// rawlen counts the number of entries recorded so far.
116// First entry is the SPACE between transmissions.
117// As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues.
118// As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts
119ISR(TIMER_INTR_NAME)
120{
121 TIMER_RESET;
122
123 uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin);
124
125 irparams.timer++; // One more 50us tick
126 if (irparams.rawlen >= RAWBUF) {
127 // Buffer overflow
128 irparams.rcvstate = STATE_STOP;
129 }
130 switch(irparams.rcvstate) {
131 case STATE_IDLE: // In the middle of a gap
132 if (irdata == MARK) {
133 if (irparams.timer < GAP_TICKS) {
134 // Not big enough to be a gap.
135 irparams.timer = 0;
136 }
137 else {
138 // gap just ended, record duration and start recording transmission
139 irparams.rawlen = 0;
140 irparams.rawbuf[irparams.rawlen++] = irparams.timer;
141 irparams.timer = 0;
142 irparams.rcvstate = STATE_MARK;
143 }
144 }
145 break;
146 case STATE_MARK: // timing MARK
147 if (irdata == SPACE) { // MARK ended, record time
148 irparams.rawbuf[irparams.rawlen++] = irparams.timer;
149 irparams.timer = 0;
150 irparams.rcvstate = STATE_SPACE;
151 }
152 break;
153 case STATE_SPACE: // timing SPACE
154 if (irdata == MARK) { // SPACE just ended, record it
155 irparams.rawbuf[irparams.rawlen++] = irparams.timer;
156 irparams.timer = 0;
157 irparams.rcvstate = STATE_MARK;
158 }
159 else { // SPACE
160 if (irparams.timer > GAP_TICKS) {
161 // big SPACE, indicates gap between codes
162 // Mark current code as ready for processing
163 // Switch to STOP
164 // Don't reset timer; keep counting space width
165 irparams.rcvstate = STATE_STOP;
166 }
167 }
168 break;
169 case STATE_STOP: // waiting, measuring gap
170 if (irdata == MARK) { // reset gap timer
171 irparams.timer = 0;
172 }
173 break;
174 }
175
176 if (irparams.blinkflag) {
177 if (irdata == MARK) {
178 BLINKLED_ON(); // turn pin 13 LED on
179 }
180 else {
181 BLINKLED_OFF(); // turn pin 13 LED off
182 }
183 }
184}
185
186void IRrecv::resume() {
187 irparams.rcvstate = STATE_IDLE;
188 irparams.rawlen = 0;
189}
190
191
192
193// Decodes the received IR message
194// Returns 0 if no data ready, 1 if data ready.
195// Results of decoding are stored in results
196int IRrecv::decode(decode_results *results) {
197 results->rawbuf = irparams.rawbuf;
198 results->rawlen = irparams.rawlen;
199 if (irparams.rcvstate != STATE_STOP) {
200 return ERR;
201 }
202
203#ifdef DEBUG
204 Serial.println("Attempting NEC decode");
205#endif
206 if (decodeNEC(results)) {
207 return DECODED;
208 }
209/*
210#ifdef DEBUG
211 Serial.println("Attempting Sony decode");
212#endif
213 if (decodeSony(results)) {
214 return DECODED;
215 }*/
216/*
217#ifdef DEBUG
218 Serial.println("Attempting Sanyo decode");
219#endif
220 if (decodeSanyo(results)) {
221 return DECODED;
222 }
223 */
224/*
225#ifdef DEBUG
226 Serial.println("Attempting Mitsubishi decode");
227#endif
228 if (decodeMitsubishi(results)) {
229 return DECODED;
230 }*/
231/*
232#ifdef DEBUG
233 Serial.println("Attempting RC5 decode");
234#endif
235 if (decodeRC5(results)) {
236 return DECODED;
237 }
238 */
239/*
240#ifdef DEBUG
241 Serial.println("Attempting RC6 decode");
242#endif
243 if (decodeRC6(results)) {
244 return DECODED;
245 }
246 */
247/*
248#ifdef DEBUG
249 Serial.println("Attempting Panasonic decode");
250#endif
251 if (decodePanasonic(results)) {
252 return DECODED;
253 }
254 */
255/*
256#ifdef DEBUG
257 Serial.println("Attempting JVC decode");
258#endif
259 if (decodeJVC(results)) {
260 return DECODED;
261 }*/
262 // decodeHash returns a hash on any input.
263 // Thus, it needs to be last in the list.
264 // If you add any decodes, add them before this.
265 if (decodeHash(results)) {
266 return DECODED;
267 }
268 // Throw away and start over
269 resume();
270 return ERR;
271}
272
273
274// NECs have a repeat only 4 items long
275long IRrecv::decodeNEC(decode_results *results) {
276 long data = 0;
277 int offset = 1; // Skip first space
278 // Initial mark
279 if (!MATCH_MARK(results->rawbuf[offset], NEC_HDR_MARK)) {
280 return ERR;
281 }
282 offset++;
283 // Check for repeat
284 if (irparams.rawlen == 4 &&
285 MATCH_SPACE(results->rawbuf[offset], NEC_RPT_SPACE) &&
286 MATCH_MARK(results->rawbuf[offset+1], NEC_BIT_MARK)) {
287 results->bits = 0;
288 results->value = REPEAT;
289 results->decode_type = NEC;
290 return DECODED;
291 }
292 if (irparams.rawlen < 2 * NEC_BITS + 4) {
293 return ERR;
294 }
295 // Initial space
296 if (!MATCH_SPACE(results->rawbuf[offset], NEC_HDR_SPACE)) {
297 return ERR;
298 }
299 offset++;
300 for (int i = 0; i < NEC_BITS; i++) {
301 if (!MATCH_MARK(results->rawbuf[offset], NEC_BIT_MARK)) {
302 return ERR;
303 }
304 offset++;
305 if (MATCH_SPACE(results->rawbuf[offset], NEC_ONE_SPACE)) {
306 data = (data << 1) | 1;
307 }
308 else if (MATCH_SPACE(results->rawbuf[offset], NEC_ZERO_SPACE)) {
309 data <<= 1;
310 }
311 else {
312 return ERR;
313 }
314 offset++;
315 }
316 // Success
317 results->bits = NEC_BITS;
318 results->value = data;
319 results->decode_type = NEC;
320 return DECODED;
321}
322/*
323long IRrecv::decodeSony(decode_results *results) {
324 long data = 0;
325 if (irparams.rawlen < 2 * SONY_BITS + 2) {
326 return ERR;
327 }
328 int offset = 0; // Dont skip first space, check its size
329
330 // Some Sony's deliver repeats fast after first
331 // unfortunately can't spot difference from of repeat from two fast clicks
332 if (results->rawbuf[offset] < SONY_DOUBLE_SPACE_USECS) {
333 // Serial.print("IR Gap found: ");
334 results->bits = 0;
335 results->value = REPEAT;
336 results->decode_type = SANYO;
337 return DECODED;
338 }
339 offset++;
340
341 // Initial mark
342 if (!MATCH_MARK(results->rawbuf[offset], SONY_HDR_MARK)) {
343 return ERR;
344 }
345 offset++;
346
347 while (offset + 1 < irparams.rawlen) {
348 if (!MATCH_SPACE(results->rawbuf[offset], SONY_HDR_SPACE)) {
349 break;
350 }
351 offset++;
352 if (MATCH_MARK(results->rawbuf[offset], SONY_ONE_MARK)) {
353 data = (data << 1) | 1;
354 }
355 else if (MATCH_MARK(results->rawbuf[offset], SONY_ZERO_MARK)) {
356 data <<= 1;
357 }
358 else {
359 return ERR;
360 }
361 offset++;
362 }
363
364 // Success
365 results->bits = (offset - 1) / 2;
366 if (results->bits < 12) {
367 results->bits = 0;
368 return ERR;
369 }
370 results->value = data;
371 results->decode_type = SONY;
372 return DECODED;
373}*/
374
375/*
376// I think this is a Sanyo decoder - serial = SA 8650B
377// Looks like Sony except for timings, 48 chars of data and time/space different
378long IRrecv::decodeSanyo(decode_results *results) {
379 long data = 0;
380 if (irparams.rawlen < 2 * SANYO_BITS + 2) {
381 return ERR;
382 }
383 int offset = 0; // Skip first space
384 // Initial space
385 // Put this back in for debugging - note can't use #DEBUG as if Debug on we don't see the repeat cos of the delay
386 //Serial.print("IR Gap: ");
387 //Serial.println( results->rawbuf[offset]);
388 //Serial.println( "test against:");
389 //Serial.println(results->rawbuf[offset]);
390
391 if (results->rawbuf[offset] < SANYO_DOUBLE_SPACE_USECS) {
392 // Serial.print("IR Gap found: ");
393 results->bits = 0;
394 results->value = REPEAT;
395 results->decode_type = SANYO;
396 return DECODED;
397 }
398 offset++;
399
400 // Initial mark
401 if (!MATCH_MARK(results->rawbuf[offset], SANYO_HDR_MARK)) {
402 return ERR;
403 }
404 offset++;
405
406 // Skip Second Mark
407 if (!MATCH_MARK(results->rawbuf[offset], SANYO_HDR_MARK)) {
408 return ERR;
409 }
410 offset++;
411
412 while (offset + 1 < irparams.rawlen) {
413 if (!MATCH_SPACE(results->rawbuf[offset], SANYO_HDR_SPACE)) {
414 break;
415 }
416 offset++;
417 if (MATCH_MARK(results->rawbuf[offset], SANYO_ONE_MARK)) {
418 data = (data << 1) | 1;
419 }
420 else if (MATCH_MARK(results->rawbuf[offset], SANYO_ZERO_MARK)) {
421 data <<= 1;
422 }
423 else {
424 return ERR;
425 }
426 offset++;
427 }
428
429 // Success
430 results->bits = (offset - 1) / 2;
431 if (results->bits < 12) {
432 results->bits = 0;
433 return ERR;
434 }
435 results->value = data;
436 results->decode_type = SANYO;
437 return DECODED;
438}
439*/
440/*
441// Looks like Sony except for timings, 48 chars of data and time/space different
442long IRrecv::decodeMitsubishi(decode_results *results) {
443 // Serial.print("?!? decoding Mitsubishi:");Serial.print(irparams.rawlen); Serial.print(" want "); Serial.println( 2 * MITSUBISHI_BITS + 2);
444 long data = 0;
445 if (irparams.rawlen < 2 * MITSUBISHI_BITS + 2) {
446 return ERR;
447 }
448 int offset = 0; // Skip first space
449 // Initial space
450 // Put this back in for debugging - note can't use #DEBUG as if Debug on we don't see the repeat cos of the delay
451 //Serial.print("IR Gap: ");
452 //Serial.println( results->rawbuf[offset]);
453 //Serial.println( "test against:");
454 //Serial.println(results->rawbuf[offset]);
455
456 // Not seeing double keys from Mitsubishi
457 //if (results->rawbuf[offset] < MITSUBISHI_DOUBLE_SPACE_USECS) {
458 // Serial.print("IR Gap found: ");
459 // results->bits = 0;
460 // results->value = REPEAT;
461 // results->decode_type = MITSUBISHI;
462 // return DECODED;
463 //}
464
465 offset++;
466
467 // Typical
468 // 14200 7 41 7 42 7 42 7 17 7 17 7 18 7 41 7 18 7 17 7 17 7 18 7 41 8 17 7 17 7 18 7 17 7
469
470 // Initial Space
471 if (!MATCH_MARK(results->rawbuf[offset], MITSUBISHI_HDR_SPACE)) {
472 return ERR;
473 }
474 offset++;
475 while (offset + 1 < irparams.rawlen) {
476 if (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ONE_MARK)) {
477 data = (data << 1) | 1;
478 }
479 else if (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ZERO_MARK)) {
480 data <<= 1;
481 }
482 else {
483 // Serial.println("A"); Serial.println(offset); Serial.println(results->rawbuf[offset]);
484 return ERR;
485 }
486 offset++;
487 if (!MATCH_SPACE(results->rawbuf[offset], MITSUBISHI_HDR_SPACE)) {
488 // Serial.println("B"); Serial.println(offset); Serial.println(results->rawbuf[offset]);
489 break;
490 }
491 offset++;
492 }
493
494 // Success
495 results->bits = (offset - 1) / 2;
496 if (results->bits < MITSUBISHI_BITS) {
497 results->bits = 0;
498 return ERR;
499 }
500 results->value = data;
501 results->decode_type = MITSUBISHI;
502 return DECODED;
503}*/
504
505
506// Gets one undecoded level at a time from the raw buffer.
507// The RC5/6 decoding is easier if the data is broken into time intervals.
508// E.g. if the buffer has MARK for 2 time intervals and SPACE for 1,
509// successive calls to getRClevel will return MARK, MARK, SPACE.
510// offset and used are updated to keep track of the current position.
511// t1 is the time interval for a single bit in microseconds.
512// Returns -1 for error (measured time interval is not a multiple of t1).
513int IRrecv::getRClevel(decode_results *results, int *offset, int *used, int t1) {
514 if (*offset >= results->rawlen) {
515 // After end of recorded buffer, assume SPACE.
516 return SPACE;
517 }
518 int width = results->rawbuf[*offset];
519 int val = ((*offset) % 2) ? MARK : SPACE;
520 int correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS;
521
522 int avail;
523 if (MATCH(width, t1 + correction)) {
524 avail = 1;
525 }
526 else if (MATCH(width, 2*t1 + correction)) {
527 avail = 2;
528 }
529 else if (MATCH(width, 3*t1 + correction)) {
530 avail = 3;
531 }
532 else {
533 return -1;
534 }
535
536 (*used)++;
537 if (*used >= avail) {
538 *used = 0;
539 (*offset)++;
540 }
541#ifdef DEBUG
542 if (val == MARK) {
543 Serial.println("MARK");
544 }
545 else {
546 Serial.println("SPACE");
547 }
548#endif
549 return val;
550}
551/*
552long IRrecv::decodeRC5(decode_results *results) {
553 if (irparams.rawlen < MIN_RC5_SAMPLES + 2) {
554 return ERR;
555 }
556 int offset = 1; // Skip gap space
557 long data = 0;
558 int used = 0;
559 // Get start bits
560 if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR;
561 if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) return ERR;
562 if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR;
563 int nbits;
564 for (nbits = 0; offset < irparams.rawlen; nbits++) {
565 int levelA = getRClevel(results, &offset, &used, RC5_T1);
566 int levelB = getRClevel(results, &offset, &used, RC5_T1);
567 if (levelA == SPACE && levelB == MARK) {
568 // 1 bit
569 data = (data << 1) | 1;
570 }
571 else if (levelA == MARK && levelB == SPACE) {
572 // zero bit
573 data <<= 1;
574 }
575 else {
576 return ERR;
577 }
578 }
579
580 // Success
581 results->bits = nbits;
582 results->value = data;
583 results->decode_type = RC5;
584 return DECODED;
585}*/
586/*
587long IRrecv::decodeRC6(decode_results *results) {
588 if (results->rawlen < MIN_RC6_SAMPLES) {
589 return ERR;
590 }
591 int offset = 1; // Skip first space
592 // Initial mark
593 if (!MATCH_MARK(results->rawbuf[offset], RC6_HDR_MARK)) {
594 return ERR;
595 }
596 offset++;
597 if (!MATCH_SPACE(results->rawbuf[offset], RC6_HDR_SPACE)) {
598 return ERR;
599 }
600 offset++;
601 long data = 0;
602 int used = 0;
603 // Get start bit (1)
604 if (getRClevel(results, &offset, &used, RC6_T1) != MARK) return ERR;
605 if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) return ERR;
606 int nbits;
607 for (nbits = 0; offset < results->rawlen; nbits++) {
608 int levelA, levelB; // Next two levels
609 levelA = getRClevel(results, &offset, &used, RC6_T1);
610 if (nbits == 3) {
611 // T bit is double wide; make sure second half matches
612 if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return ERR;
613 }
614 levelB = getRClevel(results, &offset, &used, RC6_T1);
615 if (nbits == 3) {
616 // T bit is double wide; make sure second half matches
617 if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return ERR;
618 }
619 if (levelA == MARK && levelB == SPACE) { // reversed compared to RC5
620 // 1 bit
621 data = (data << 1) | 1;
622 }
623 else if (levelA == SPACE && levelB == MARK) {
624 // zero bit
625 data <<= 1;
626 }
627 else {
628 return ERR; // Error
629 }
630 }
631 // Success
632 results->bits = nbits;
633 results->value = data;
634 results->decode_type = RC6;
635 return DECODED;
636}*/
637/*
638long IRrecv::decodePanasonic(decode_results *results) {
639 unsigned long long data = 0;
640 int offset = 1;
641
642 if (!MATCH_MARK(results->rawbuf[offset], PANASONIC_HDR_MARK)) {
643 return ERR;
644 }
645 offset++;
646 if (!MATCH_MARK(results->rawbuf[offset], PANASONIC_HDR_SPACE)) {
647 return ERR;
648 }
649 offset++;
650
651 // decode address
652 for (int i = 0; i < PANASONIC_BITS; i++) {
653 if (!MATCH_MARK(results->rawbuf[offset++], PANASONIC_BIT_MARK)) {
654 return ERR;
655 }
656 if (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ONE_SPACE)) {
657 data = (data << 1) | 1;
658 } else if (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ZERO_SPACE)) {
659 data <<= 1;
660 } else {
661 return ERR;
662 }
663 offset++;
664 }
665 results->value = (unsigned long)data;
666 results->panasonicAddress = (unsigned int)(data >> 32);
667 results->decode_type = PANASONIC;
668 results->bits = PANASONIC_BITS;
669 return DECODED;
670}*/
671/*
672long IRrecv::decodeJVC(decode_results *results) {
673 long data = 0;
674 int offset = 1; // Skip first space
675 // Check for repeat
676 if (irparams.rawlen - 1 == 33 &&
677 MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK) &&
678 MATCH_MARK(results->rawbuf[irparams.rawlen-1], JVC_BIT_MARK)) {
679 results->bits = 0;
680 results->value = REPEAT;
681 results->decode_type = JVC;
682 return DECODED;
683 }
684 // Initial mark
685 if (!MATCH_MARK(results->rawbuf[offset], JVC_HDR_MARK)) {
686 return ERR;
687 }
688 offset++;
689 if (irparams.rawlen < 2 * JVC_BITS + 1 ) {
690 return ERR;
691 }
692 // Initial space
693 if (!MATCH_SPACE(results->rawbuf[offset], JVC_HDR_SPACE)) {
694 return ERR;
695 }
696 offset++;
697 for (int i = 0; i < JVC_BITS; i++) {
698 if (!MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK)) {
699 return ERR;
700 }
701 offset++;
702 if (MATCH_SPACE(results->rawbuf[offset], JVC_ONE_SPACE)) {
703 data = (data << 1) | 1;
704 }
705 else if (MATCH_SPACE(results->rawbuf[offset], JVC_ZERO_SPACE)) {
706 data <<= 1;
707 }
708 else {
709 return ERR;
710 }
711 offset++;
712 }
713 //Stop bit
714 if (!MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK)){
715 return ERR;
716 }
717 // Success
718 results->bits = JVC_BITS;
719 results->value = data;
720 results->decode_type = JVC;
721 return DECODED;
722}*/
723
724/* -----------------------------------------------------------------------
725 * hashdecode - decode an arbitrary IR code.
726 * Instead of decoding using a standard encoding scheme
727 * (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value.
728 *
729 * The algorithm: look at the sequence of MARK signals, and see if each one
730 * is shorter (0), the same length (1), or longer (2) than the previous.
731 * Do the same with the SPACE signals. Hszh the resulting sequence of 0's,
732 * 1's, and 2's to a 32-bit value. This will give a unique value for each
733 * different code (probably), for most code systems.
734 *
735 * http://arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html
736 */
737
738// Compare two tick values, returning 0 if newval is shorter,
739// 1 if newval is equal, and 2 if newval is longer
740// Use a tolerance of 20%
741int IRrecv::compare(unsigned int oldval, unsigned int newval) {
742 if (newval < oldval * .8) {
743 return 0;
744 }
745 else if (oldval < newval * .8) {
746 return 2;
747 }
748 else {
749 return 1;
750 }
751}
752
753// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param
754#define FNV_PRIME_32 16777619
755#define FNV_BASIS_32 2166136261
756
757/* Converts the raw code values into a 32-bit hash code.
758 * Hopefully this code is unique for each button.
759 * This isn't a "real" decoding, just an arbitrary value.
760 */
761long IRrecv::decodeHash(decode_results *results) {
762 // Require at least 6 samples to prevent triggering on noise
763 if (results->rawlen < 6) {
764 return ERR;
765 }
766 long hash = FNV_BASIS_32;
767 for (int i = 1; i+2 < results->rawlen; i++) {
768 int value = compare(results->rawbuf[i], results->rawbuf[i+2]);
769 // Add value into the hash
770 hash = (hash * FNV_PRIME_32) ^ value;
771 }
772 results->value = hash;
773 results->bits = 32;
774 results->decode_type = UNKNOWN;
775 return DECODED;
776}
777
Note: See TracBrowser for help on using the repository browser.