source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/libraries/RobotIRremote/src/IRremote.cpp @ 46

Last change on this file since 46 was 46, checked in by jrpelegrina, 4 years ago

First release to Xenial

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.