comparison service/busyboxArduino/IRremote/IRremote.cpp @ 155:e88308cea843

add IRremote Ignore-this: c295c68f923af8d072841f1d7c1e5ab8
author drewp@bigasterisk.com
date Mon, 19 Jan 2015 17:55:26 -0800
parents
children
comparison
equal deleted inserted replaced
154:58c47bfe0ce5 155:e88308cea843
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 * LG added by Darryl Smith (based on the JVC protocol)
18 */
19
20 #include "IRremote.h"
21 #include "IRremoteInt.h"
22
23 // Provides ISR
24 #include <avr/interrupt.h>
25
26 volatile irparams_t irparams;
27
28 // These versions of MATCH, MATCH_MARK, and MATCH_SPACE are only for debugging.
29 // To use them, set DEBUG in IRremoteInt.h
30 // Normally macros are used for efficiency
31 #ifdef DEBUG
32 int MATCH(int measured, int desired) {
33 Serial.print("Testing: ");
34 Serial.print(TICKS_LOW(desired), DEC);
35 Serial.print(" <= ");
36 Serial.print(measured, DEC);
37 Serial.print(" <= ");
38 Serial.println(TICKS_HIGH(desired), DEC);
39 return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);
40 }
41
42 int MATCH_MARK(int measured_ticks, int desired_us) {
43 Serial.print("Testing mark ");
44 Serial.print(measured_ticks * USECPERTICK, DEC);
45 Serial.print(" vs ");
46 Serial.print(desired_us, DEC);
47 Serial.print(": ");
48 Serial.print(TICKS_LOW(desired_us + MARK_EXCESS), DEC);
49 Serial.print(" <= ");
50 Serial.print(measured_ticks, DEC);
51 Serial.print(" <= ");
52 Serial.println(TICKS_HIGH(desired_us + MARK_EXCESS), DEC);
53 return measured_ticks >= TICKS_LOW(desired_us + MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS);
54 }
55
56 int MATCH_SPACE(int measured_ticks, int desired_us) {
57 Serial.print("Testing space ");
58 Serial.print(measured_ticks * USECPERTICK, DEC);
59 Serial.print(" vs ");
60 Serial.print(desired_us, DEC);
61 Serial.print(": ");
62 Serial.print(TICKS_LOW(desired_us - MARK_EXCESS), DEC);
63 Serial.print(" <= ");
64 Serial.print(measured_ticks, DEC);
65 Serial.print(" <= ");
66 Serial.println(TICKS_HIGH(desired_us - MARK_EXCESS), DEC);
67 return measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS);
68 }
69 #else
70 int MATCH(int measured, int desired) {return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);}
71 int MATCH_MARK(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us + MARK_EXCESS));}
72 int MATCH_SPACE(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us - MARK_EXCESS));}
73 // Debugging versions are in IRremote.cpp
74 #endif
75
76 void IRsend::sendNEC(unsigned long data, int nbits)
77 {
78 enableIROut(38);
79 mark(NEC_HDR_MARK);
80 space(NEC_HDR_SPACE);
81 for (int i = 0; i < nbits; i++) {
82 if (data & TOPBIT) {
83 mark(NEC_BIT_MARK);
84 space(NEC_ONE_SPACE);
85 }
86 else {
87 mark(NEC_BIT_MARK);
88 space(NEC_ZERO_SPACE);
89 }
90 data <<= 1;
91 }
92 mark(NEC_BIT_MARK);
93 space(0);
94 }
95
96 void IRsend::sendSony(unsigned long data, int nbits) {
97 enableIROut(40);
98 mark(SONY_HDR_MARK);
99 space(SONY_HDR_SPACE);
100 data = data << (32 - nbits);
101 for (int i = 0; i < nbits; i++) {
102 if (data & TOPBIT) {
103 mark(SONY_ONE_MARK);
104 space(SONY_HDR_SPACE);
105 }
106 else {
107 mark(SONY_ZERO_MARK);
108 space(SONY_HDR_SPACE);
109 }
110 data <<= 1;
111 }
112 }
113
114 void IRsend::sendRaw(unsigned int buf[], int len, int hz)
115 {
116 enableIROut(hz);
117 for (int i = 0; i < len; i++) {
118 if (i & 1) {
119 space(buf[i]);
120 }
121 else {
122 mark(buf[i]);
123 }
124 }
125 space(0); // Just to be sure
126 }
127
128 // Note: first bit must be a one (start bit)
129 void IRsend::sendRC5(unsigned long data, int nbits)
130 {
131 enableIROut(36);
132 data = data << (32 - nbits);
133 mark(RC5_T1); // First start bit
134 space(RC5_T1); // Second start bit
135 mark(RC5_T1); // Second start bit
136 for (int i = 0; i < nbits; i++) {
137 if (data & TOPBIT) {
138 space(RC5_T1); // 1 is space, then mark
139 mark(RC5_T1);
140 }
141 else {
142 mark(RC5_T1);
143 space(RC5_T1);
144 }
145 data <<= 1;
146 }
147 space(0); // Turn off at end
148 }
149
150 // Caller needs to take care of flipping the toggle bit
151 void IRsend::sendRC6(unsigned long data, int nbits)
152 {
153 enableIROut(36);
154 data = data << (32 - nbits);
155 mark(RC6_HDR_MARK);
156 space(RC6_HDR_SPACE);
157 mark(RC6_T1); // start bit
158 space(RC6_T1);
159 int t;
160 for (int i = 0; i < nbits; i++) {
161 if (i == 3) {
162 // double-wide trailer bit
163 t = 2 * RC6_T1;
164 }
165 else {
166 t = RC6_T1;
167 }
168 if (data & TOPBIT) {
169 mark(t);
170 space(t);
171 }
172 else {
173 space(t);
174 mark(t);
175 }
176
177 data <<= 1;
178 }
179 space(0); // Turn off at end
180 }
181 void IRsend::sendPanasonic(unsigned int address, unsigned long data) {
182 enableIROut(35);
183 mark(PANASONIC_HDR_MARK);
184 space(PANASONIC_HDR_SPACE);
185
186 for(int i=0;i<16;i++)
187 {
188 mark(PANASONIC_BIT_MARK);
189 if (address & 0x8000) {
190 space(PANASONIC_ONE_SPACE);
191 } else {
192 space(PANASONIC_ZERO_SPACE);
193 }
194 address <<= 1;
195 }
196 for (int i=0; i < 32; i++) {
197 mark(PANASONIC_BIT_MARK);
198 if (data & TOPBIT) {
199 space(PANASONIC_ONE_SPACE);
200 } else {
201 space(PANASONIC_ZERO_SPACE);
202 }
203 data <<= 1;
204 }
205 mark(PANASONIC_BIT_MARK);
206 space(0);
207 }
208 void IRsend::sendJVC(unsigned long data, int nbits, int repeat)
209 {
210 enableIROut(38);
211 data = data << (32 - nbits);
212 if (!repeat){
213 mark(JVC_HDR_MARK);
214 space(JVC_HDR_SPACE);
215 }
216 for (int i = 0; i < nbits; i++) {
217 if (data & TOPBIT) {
218 mark(JVC_BIT_MARK);
219 space(JVC_ONE_SPACE);
220 }
221 else {
222 mark(JVC_BIT_MARK);
223 space(JVC_ZERO_SPACE);
224 }
225 data <<= 1;
226 }
227 mark(JVC_BIT_MARK);
228 space(0);
229 }
230
231 void IRsend::sendSAMSUNG(unsigned long data, int nbits)
232 {
233 enableIROut(38);
234 mark(SAMSUNG_HDR_MARK);
235 space(SAMSUNG_HDR_SPACE);
236 for (int i = 0; i < nbits; i++) {
237 if (data & TOPBIT) {
238 mark(SAMSUNG_BIT_MARK);
239 space(SAMSUNG_ONE_SPACE);
240 }
241 else {
242 mark(SAMSUNG_BIT_MARK);
243 space(SAMSUNG_ZERO_SPACE);
244 }
245 data <<= 1;
246 }
247 mark(SAMSUNG_BIT_MARK);
248 space(0);
249 }
250
251 void IRsend::mark(int time) {
252 // Sends an IR mark for the specified number of microseconds.
253 // The mark output is modulated at the PWM frequency.
254 TIMER_ENABLE_PWM; // Enable pin 3 PWM output
255 if (time > 0) delayMicroseconds(time);
256 }
257
258 /* Leave pin off for time (given in microseconds) */
259 void IRsend::space(int time) {
260 // Sends an IR space for the specified number of microseconds.
261 // A space is no output, so the PWM output is disabled.
262 TIMER_DISABLE_PWM; // Disable pin 3 PWM output
263 if (time > 0) delayMicroseconds(time);
264 }
265
266 void IRsend::enableIROut(int khz) {
267 // Enables IR output. The khz value controls the modulation frequency in kilohertz.
268 // The IR output will be on pin 3 (OC2B).
269 // This routine is designed for 36-40KHz; if you use it for other values, it's up to you
270 // to make sure it gives reasonable results. (Watch out for overflow / underflow / rounding.)
271 // TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B
272 // controlling the duty cycle.
273 // There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A)
274 // To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.
275 // A few hours staring at the ATmega documentation and this will all make sense.
276 // See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.
277
278
279 // Disable the Timer2 Interrupt (which is used for receiving IR)
280 TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt
281
282 pinMode(TIMER_PWM_PIN, OUTPUT);
283 digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low
284
285 // COM2A = 00: disconnect OC2A
286 // COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted
287 // WGM2 = 101: phase-correct PWM with OCRA as top
288 // CS2 = 000: no prescaling
289 // The top value for the timer. The modulation frequency will be SYSCLOCK / 2 / OCR2A.
290 TIMER_CONFIG_KHZ(khz);
291 }
292
293 IRrecv::IRrecv(int recvpin)
294 {
295 irparams.recvpin = recvpin;
296 irparams.blinkflag = 0;
297 }
298
299 // initialization
300 void IRrecv::enableIRIn() {
301 cli();
302 // setup pulse clock timer interrupt
303 //Prescale /8 (16M/8 = 0.5 microseconds per tick)
304 // Therefore, the timer interval can range from 0.5 to 128 microseconds
305 // depending on the reset value (255 to 0)
306 TIMER_CONFIG_NORMAL();
307
308 //Timer2 Overflow Interrupt Enable
309 TIMER_ENABLE_INTR;
310
311 TIMER_RESET;
312
313 sei(); // enable interrupts
314
315 // initialize state machine variables
316 irparams.rcvstate = STATE_IDLE;
317 irparams.rawlen = 0;
318
319 // set pin modes
320 pinMode(irparams.recvpin, INPUT);
321 }
322
323 // enable/disable blinking of pin 13 on IR processing
324 void IRrecv::blink13(int blinkflag)
325 {
326 irparams.blinkflag = blinkflag;
327 if (blinkflag)
328 pinMode(BLINKLED, OUTPUT);
329 }
330
331 // TIMER2 interrupt code to collect raw data.
332 // Widths of alternating SPACE, MARK are recorded in rawbuf.
333 // Recorded in ticks of 50 microseconds.
334 // rawlen counts the number of entries recorded so far.
335 // First entry is the SPACE between transmissions.
336 // As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues.
337 // As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts
338 ISR(TIMER_INTR_NAME)
339 {
340 TIMER_RESET;
341
342 uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin);
343
344 irparams.timer++; // One more 50us tick
345 if (irparams.rawlen >= RAWBUF) {
346 // Buffer overflow
347 irparams.rcvstate = STATE_STOP;
348 }
349 switch(irparams.rcvstate) {
350 case STATE_IDLE: // In the middle of a gap
351 if (irdata == MARK) {
352 if (irparams.timer < GAP_TICKS) {
353 // Not big enough to be a gap.
354 irparams.timer = 0;
355 }
356 else {
357 // gap just ended, record duration and start recording transmission
358 irparams.rawlen = 0;
359 irparams.rawbuf[irparams.rawlen++] = irparams.timer;
360 irparams.timer = 0;
361 irparams.rcvstate = STATE_MARK;
362 }
363 }
364 break;
365 case STATE_MARK: // timing MARK
366 if (irdata == SPACE) { // MARK ended, record time
367 irparams.rawbuf[irparams.rawlen++] = irparams.timer;
368 irparams.timer = 0;
369 irparams.rcvstate = STATE_SPACE;
370 }
371 break;
372 case STATE_SPACE: // timing SPACE
373 if (irdata == MARK) { // SPACE just ended, record it
374 irparams.rawbuf[irparams.rawlen++] = irparams.timer;
375 irparams.timer = 0;
376 irparams.rcvstate = STATE_MARK;
377 }
378 else { // SPACE
379 if (irparams.timer > GAP_TICKS) {
380 // big SPACE, indicates gap between codes
381 // Mark current code as ready for processing
382 // Switch to STOP
383 // Don't reset timer; keep counting space width
384 irparams.rcvstate = STATE_STOP;
385 }
386 }
387 break;
388 case STATE_STOP: // waiting, measuring gap
389 if (irdata == MARK) { // reset gap timer
390 irparams.timer = 0;
391 }
392 break;
393 }
394
395 if (irparams.blinkflag) {
396 if (irdata == MARK) {
397 BLINKLED_ON(); // turn pin 13 LED on
398 }
399 else {
400 BLINKLED_OFF(); // turn pin 13 LED off
401 }
402 }
403 }
404
405 void IRrecv::resume() {
406 irparams.rcvstate = STATE_IDLE;
407 irparams.rawlen = 0;
408 }
409
410
411
412 // Decodes the received IR message
413 // Returns 0 if no data ready, 1 if data ready.
414 // Results of decoding are stored in results
415 int IRrecv::decode(decode_results *results) {
416 results->rawbuf = irparams.rawbuf;
417 results->rawlen = irparams.rawlen;
418 if (irparams.rcvstate != STATE_STOP) {
419 return ERR;
420 }
421 #ifdef DEBUG
422 Serial.println("Attempting NEC decode");
423 #endif
424 if (decodeNEC(results)) {
425 return DECODED;
426 }
427 #ifdef DEBUG
428 Serial.println("Attempting Sony decode");
429 #endif
430 if (decodeSony(results)) {
431 return DECODED;
432 }
433 #ifdef DEBUG
434 Serial.println("Attempting Sanyo decode");
435 #endif
436 if (decodeSanyo(results)) {
437 return DECODED;
438 }
439 #ifdef DEBUG
440 Serial.println("Attempting Mitsubishi decode");
441 #endif
442 if (decodeMitsubishi(results)) {
443 return DECODED;
444 }
445 #ifdef DEBUG
446 Serial.println("Attempting RC5 decode");
447 #endif
448 if (decodeRC5(results)) {
449 return DECODED;
450 }
451 #ifdef DEBUG
452 Serial.println("Attempting RC6 decode");
453 #endif
454 if (decodeRC6(results)) {
455 return DECODED;
456 }
457 #ifdef DEBUG
458 Serial.println("Attempting Panasonic decode");
459 #endif
460 if (decodePanasonic(results)) {
461 return DECODED;
462 }
463 #ifdef DEBUG
464 Serial.println("Attempting LG decode");
465 #endif
466 if (decodeLG(results)) {
467 return DECODED;
468 }
469 #ifdef DEBUG
470 Serial.println("Attempting JVC decode");
471 #endif
472 if (decodeJVC(results)) {
473 return DECODED;
474 }
475 #ifdef DEBUG
476 Serial.println("Attempting SAMSUNG decode");
477 #endif
478 if (decodeSAMSUNG(results)) {
479 return DECODED;
480 }
481 // decodeHash returns a hash on any input.
482 // Thus, it needs to be last in the list.
483 // If you add any decodes, add them before this.
484 if (decodeHash(results)) {
485 return DECODED;
486 }
487 // Throw away and start over
488 resume();
489 return ERR;
490 }
491
492 // NECs have a repeat only 4 items long
493 long IRrecv::decodeNEC(decode_results *results) {
494 long data = 0;
495 int offset = 1; // Skip first space
496 // Initial mark
497 if (!MATCH_MARK(results->rawbuf[offset], NEC_HDR_MARK)) {
498 return ERR;
499 }
500 offset++;
501 // Check for repeat
502 if (irparams.rawlen == 4 &&
503 MATCH_SPACE(results->rawbuf[offset], NEC_RPT_SPACE) &&
504 MATCH_MARK(results->rawbuf[offset+1], NEC_BIT_MARK)) {
505 results->bits = 0;
506 results->value = REPEAT;
507 results->decode_type = NEC;
508 return DECODED;
509 }
510 if (irparams.rawlen < 2 * NEC_BITS + 4) {
511 return ERR;
512 }
513 // Initial space
514 if (!MATCH_SPACE(results->rawbuf[offset], NEC_HDR_SPACE)) {
515 return ERR;
516 }
517 offset++;
518 for (int i = 0; i < NEC_BITS; i++) {
519 if (!MATCH_MARK(results->rawbuf[offset], NEC_BIT_MARK)) {
520 return ERR;
521 }
522 offset++;
523 if (MATCH_SPACE(results->rawbuf[offset], NEC_ONE_SPACE)) {
524 data = (data << 1) | 1;
525 }
526 else if (MATCH_SPACE(results->rawbuf[offset], NEC_ZERO_SPACE)) {
527 data <<= 1;
528 }
529 else {
530 return ERR;
531 }
532 offset++;
533 }
534 // Success
535 results->bits = NEC_BITS;
536 results->value = data;
537 results->decode_type = NEC;
538 return DECODED;
539 }
540
541 long IRrecv::decodeSony(decode_results *results) {
542 long data = 0;
543 if (irparams.rawlen < 2 * SONY_BITS + 2) {
544 return ERR;
545 }
546 int offset = 0; // Dont skip first space, check its size
547
548 // Some Sony's deliver repeats fast after first
549 // unfortunately can't spot difference from of repeat from two fast clicks
550 if (results->rawbuf[offset] < SONY_DOUBLE_SPACE_USECS) {
551 // Serial.print("IR Gap found: ");
552 results->bits = 0;
553 results->value = REPEAT;
554 results->decode_type = SANYO;
555 return DECODED;
556 }
557 offset++;
558
559 // Initial mark
560 if (!MATCH_MARK(results->rawbuf[offset], SONY_HDR_MARK)) {
561 return ERR;
562 }
563 offset++;
564
565 while (offset + 1 < irparams.rawlen) {
566 if (!MATCH_SPACE(results->rawbuf[offset], SONY_HDR_SPACE)) {
567 break;
568 }
569 offset++;
570 if (MATCH_MARK(results->rawbuf[offset], SONY_ONE_MARK)) {
571 data = (data << 1) | 1;
572 }
573 else if (MATCH_MARK(results->rawbuf[offset], SONY_ZERO_MARK)) {
574 data <<= 1;
575 }
576 else {
577 return ERR;
578 }
579 offset++;
580 }
581
582 // Success
583 results->bits = (offset - 1) / 2;
584 if (results->bits < 12) {
585 results->bits = 0;
586 return ERR;
587 }
588 results->value = data;
589 results->decode_type = SONY;
590 return DECODED;
591 }
592
593 // I think this is a Sanyo decoder - serial = SA 8650B
594 // Looks like Sony except for timings, 48 chars of data and time/space different
595 long IRrecv::decodeSanyo(decode_results *results) {
596 long data = 0;
597 if (irparams.rawlen < 2 * SANYO_BITS + 2) {
598 return ERR;
599 }
600 int offset = 0; // Skip first space
601 // Initial space
602 /* 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
603 Serial.print("IR Gap: ");
604 Serial.println( results->rawbuf[offset]);
605 Serial.println( "test against:");
606 Serial.println(results->rawbuf[offset]);
607 */
608 if (results->rawbuf[offset] < SANYO_DOUBLE_SPACE_USECS) {
609 // Serial.print("IR Gap found: ");
610 results->bits = 0;
611 results->value = REPEAT;
612 results->decode_type = SANYO;
613 return DECODED;
614 }
615 offset++;
616
617 // Initial mark
618 if (!MATCH_MARK(results->rawbuf[offset], SANYO_HDR_MARK)) {
619 return ERR;
620 }
621 offset++;
622
623 // Skip Second Mark
624 if (!MATCH_MARK(results->rawbuf[offset], SANYO_HDR_MARK)) {
625 return ERR;
626 }
627 offset++;
628
629 while (offset + 1 < irparams.rawlen) {
630 if (!MATCH_SPACE(results->rawbuf[offset], SANYO_HDR_SPACE)) {
631 break;
632 }
633 offset++;
634 if (MATCH_MARK(results->rawbuf[offset], SANYO_ONE_MARK)) {
635 data = (data << 1) | 1;
636 }
637 else if (MATCH_MARK(results->rawbuf[offset], SANYO_ZERO_MARK)) {
638 data <<= 1;
639 }
640 else {
641 return ERR;
642 }
643 offset++;
644 }
645
646 // Success
647 results->bits = (offset - 1) / 2;
648 if (results->bits < 12) {
649 results->bits = 0;
650 return ERR;
651 }
652 results->value = data;
653 results->decode_type = SANYO;
654 return DECODED;
655 }
656
657 // Looks like Sony except for timings, 48 chars of data and time/space different
658 long IRrecv::decodeMitsubishi(decode_results *results) {
659 // Serial.print("?!? decoding Mitsubishi:");Serial.print(irparams.rawlen); Serial.print(" want "); Serial.println( 2 * MITSUBISHI_BITS + 2);
660 long data = 0;
661 if (irparams.rawlen < 2 * MITSUBISHI_BITS + 2) {
662 return ERR;
663 }
664 int offset = 0; // Skip first space
665 // Initial space
666 /* 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
667 Serial.print("IR Gap: ");
668 Serial.println( results->rawbuf[offset]);
669 Serial.println( "test against:");
670 Serial.println(results->rawbuf[offset]);
671 */
672 /* Not seeing double keys from Mitsubishi
673 if (results->rawbuf[offset] < MITSUBISHI_DOUBLE_SPACE_USECS) {
674 // Serial.print("IR Gap found: ");
675 results->bits = 0;
676 results->value = REPEAT;
677 results->decode_type = MITSUBISHI;
678 return DECODED;
679 }
680 */
681 offset++;
682
683 // Typical
684 // 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
685
686 // Initial Space
687 if (!MATCH_MARK(results->rawbuf[offset], MITSUBISHI_HDR_SPACE)) {
688 return ERR;
689 }
690 offset++;
691 while (offset + 1 < irparams.rawlen) {
692 if (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ONE_MARK)) {
693 data = (data << 1) | 1;
694 }
695 else if (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ZERO_MARK)) {
696 data <<= 1;
697 }
698 else {
699 // Serial.println("A"); Serial.println(offset); Serial.println(results->rawbuf[offset]);
700 return ERR;
701 }
702 offset++;
703 if (!MATCH_SPACE(results->rawbuf[offset], MITSUBISHI_HDR_SPACE)) {
704 // Serial.println("B"); Serial.println(offset); Serial.println(results->rawbuf[offset]);
705 break;
706 }
707 offset++;
708 }
709
710 // Success
711 results->bits = (offset - 1) / 2;
712 if (results->bits < MITSUBISHI_BITS) {
713 results->bits = 0;
714 return ERR;
715 }
716 results->value = data;
717 results->decode_type = MITSUBISHI;
718 return DECODED;
719 }
720
721
722 // Gets one undecoded level at a time from the raw buffer.
723 // The RC5/6 decoding is easier if the data is broken into time intervals.
724 // E.g. if the buffer has MARK for 2 time intervals and SPACE for 1,
725 // successive calls to getRClevel will return MARK, MARK, SPACE.
726 // offset and used are updated to keep track of the current position.
727 // t1 is the time interval for a single bit in microseconds.
728 // Returns -1 for error (measured time interval is not a multiple of t1).
729 int IRrecv::getRClevel(decode_results *results, int *offset, int *used, int t1) {
730 if (*offset >= results->rawlen) {
731 // After end of recorded buffer, assume SPACE.
732 return SPACE;
733 }
734 int width = results->rawbuf[*offset];
735 int val = ((*offset) % 2) ? MARK : SPACE;
736 int correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS;
737
738 int avail;
739 if (MATCH(width, t1 + correction)) {
740 avail = 1;
741 }
742 else if (MATCH(width, 2*t1 + correction)) {
743 avail = 2;
744 }
745 else if (MATCH(width, 3*t1 + correction)) {
746 avail = 3;
747 }
748 else {
749 return -1;
750 }
751
752 (*used)++;
753 if (*used >= avail) {
754 *used = 0;
755 (*offset)++;
756 }
757 #ifdef DEBUG
758 if (val == MARK) {
759 Serial.println("MARK");
760 }
761 else {
762 Serial.println("SPACE");
763 }
764 #endif
765 return val;
766 }
767
768 long IRrecv::decodeRC5(decode_results *results) {
769 if (irparams.rawlen < MIN_RC5_SAMPLES + 2) {
770 return ERR;
771 }
772 int offset = 1; // Skip gap space
773 long data = 0;
774 int used = 0;
775 // Get start bits
776 if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR;
777 if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) return ERR;
778 if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR;
779 int nbits;
780 for (nbits = 0; offset < irparams.rawlen; nbits++) {
781 int levelA = getRClevel(results, &offset, &used, RC5_T1);
782 int levelB = getRClevel(results, &offset, &used, RC5_T1);
783 if (levelA == SPACE && levelB == MARK) {
784 // 1 bit
785 data = (data << 1) | 1;
786 }
787 else if (levelA == MARK && levelB == SPACE) {
788 // zero bit
789 data <<= 1;
790 }
791 else {
792 return ERR;
793 }
794 }
795
796 // Success
797 results->bits = nbits;
798 results->value = data;
799 results->decode_type = RC5;
800 return DECODED;
801 }
802
803 long IRrecv::decodeRC6(decode_results *results) {
804 if (results->rawlen < MIN_RC6_SAMPLES) {
805 return ERR;
806 }
807 int offset = 1; // Skip first space
808 // Initial mark
809 if (!MATCH_MARK(results->rawbuf[offset], RC6_HDR_MARK)) {
810 return ERR;
811 }
812 offset++;
813 if (!MATCH_SPACE(results->rawbuf[offset], RC6_HDR_SPACE)) {
814 return ERR;
815 }
816 offset++;
817 long data = 0;
818 int used = 0;
819 // Get start bit (1)
820 if (getRClevel(results, &offset, &used, RC6_T1) != MARK) return ERR;
821 if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) return ERR;
822 int nbits;
823 for (nbits = 0; offset < results->rawlen; nbits++) {
824 int levelA, levelB; // Next two levels
825 levelA = getRClevel(results, &offset, &used, RC6_T1);
826 if (nbits == 3) {
827 // T bit is double wide; make sure second half matches
828 if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return ERR;
829 }
830 levelB = getRClevel(results, &offset, &used, RC6_T1);
831 if (nbits == 3) {
832 // T bit is double wide; make sure second half matches
833 if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return ERR;
834 }
835 if (levelA == MARK && levelB == SPACE) { // reversed compared to RC5
836 // 1 bit
837 data = (data << 1) | 1;
838 }
839 else if (levelA == SPACE && levelB == MARK) {
840 // zero bit
841 data <<= 1;
842 }
843 else {
844 return ERR; // Error
845 }
846 }
847 // Success
848 results->bits = nbits;
849 results->value = data;
850 results->decode_type = RC6;
851 return DECODED;
852 }
853 long IRrecv::decodePanasonic(decode_results *results) {
854 unsigned long long data = 0;
855 int offset = 1;
856
857 if (!MATCH_MARK(results->rawbuf[offset], PANASONIC_HDR_MARK)) {
858 return ERR;
859 }
860 offset++;
861 if (!MATCH_MARK(results->rawbuf[offset], PANASONIC_HDR_SPACE)) {
862 return ERR;
863 }
864 offset++;
865
866 // decode address
867 for (int i = 0; i < PANASONIC_BITS; i++) {
868 if (!MATCH_MARK(results->rawbuf[offset++], PANASONIC_BIT_MARK)) {
869 return ERR;
870 }
871 if (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ONE_SPACE)) {
872 data = (data << 1) | 1;
873 } else if (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ZERO_SPACE)) {
874 data <<= 1;
875 } else {
876 return ERR;
877 }
878 offset++;
879 }
880 results->value = (unsigned long)data;
881 results->panasonicAddress = (unsigned int)(data >> 32);
882 results->decode_type = PANASONIC;
883 results->bits = PANASONIC_BITS;
884 return DECODED;
885 }
886
887 long IRrecv::decodeLG(decode_results *results) {
888 long data = 0;
889 int offset = 1; // Skip first space
890
891 // Initial mark
892 if (!MATCH_MARK(results->rawbuf[offset], LG_HDR_MARK)) {
893 return ERR;
894 }
895 offset++;
896 if (irparams.rawlen < 2 * LG_BITS + 1 ) {
897 return ERR;
898 }
899 // Initial space
900 if (!MATCH_SPACE(results->rawbuf[offset], LG_HDR_SPACE)) {
901 return ERR;
902 }
903 offset++;
904 for (int i = 0; i < LG_BITS; i++) {
905 if (!MATCH_MARK(results->rawbuf[offset], LG_BIT_MARK)) {
906 return ERR;
907 }
908 offset++;
909 if (MATCH_SPACE(results->rawbuf[offset], LG_ONE_SPACE)) {
910 data = (data << 1) | 1;
911 }
912 else if (MATCH_SPACE(results->rawbuf[offset], LG_ZERO_SPACE)) {
913 data <<= 1;
914 }
915 else {
916 return ERR;
917 }
918 offset++;
919 }
920 //Stop bit
921 if (!MATCH_MARK(results->rawbuf[offset], LG_BIT_MARK)){
922 return ERR;
923 }
924 // Success
925 results->bits = LG_BITS;
926 results->value = data;
927 results->decode_type = LG;
928 return DECODED;
929 }
930
931
932 long IRrecv::decodeJVC(decode_results *results) {
933 long data = 0;
934 int offset = 1; // Skip first space
935 // Check for repeat
936 if (irparams.rawlen - 1 == 33 &&
937 MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK) &&
938 MATCH_MARK(results->rawbuf[irparams.rawlen-1], JVC_BIT_MARK)) {
939 results->bits = 0;
940 results->value = REPEAT;
941 results->decode_type = JVC;
942 return DECODED;
943 }
944 // Initial mark
945 if (!MATCH_MARK(results->rawbuf[offset], JVC_HDR_MARK)) {
946 return ERR;
947 }
948 offset++;
949 if (irparams.rawlen < 2 * JVC_BITS + 1 ) {
950 return ERR;
951 }
952 // Initial space
953 if (!MATCH_SPACE(results->rawbuf[offset], JVC_HDR_SPACE)) {
954 return ERR;
955 }
956 offset++;
957 for (int i = 0; i < JVC_BITS; i++) {
958 if (!MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK)) {
959 return ERR;
960 }
961 offset++;
962 if (MATCH_SPACE(results->rawbuf[offset], JVC_ONE_SPACE)) {
963 data = (data << 1) | 1;
964 }
965 else if (MATCH_SPACE(results->rawbuf[offset], JVC_ZERO_SPACE)) {
966 data <<= 1;
967 }
968 else {
969 return ERR;
970 }
971 offset++;
972 }
973 //Stop bit
974 if (!MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK)){
975 return ERR;
976 }
977 // Success
978 results->bits = JVC_BITS;
979 results->value = data;
980 results->decode_type = JVC;
981 return DECODED;
982 }
983
984 // SAMSUNGs have a repeat only 4 items long
985 long IRrecv::decodeSAMSUNG(decode_results *results) {
986 long data = 0;
987 int offset = 1; // Skip first space
988 // Initial mark
989 if (!MATCH_MARK(results->rawbuf[offset], SAMSUNG_HDR_MARK)) {
990 return ERR;
991 }
992 offset++;
993 // Check for repeat
994 if (irparams.rawlen == 4 &&
995 MATCH_SPACE(results->rawbuf[offset], SAMSUNG_RPT_SPACE) &&
996 MATCH_MARK(results->rawbuf[offset+1], SAMSUNG_BIT_MARK)) {
997 results->bits = 0;
998 results->value = REPEAT;
999 results->decode_type = SAMSUNG;
1000 return DECODED;
1001 }
1002 if (irparams.rawlen < 2 * SAMSUNG_BITS + 4) {
1003 return ERR;
1004 }
1005 // Initial space
1006 if (!MATCH_SPACE(results->rawbuf[offset], SAMSUNG_HDR_SPACE)) {
1007 return ERR;
1008 }
1009 offset++;
1010 for (int i = 0; i < SAMSUNG_BITS; i++) {
1011 if (!MATCH_MARK(results->rawbuf[offset], SAMSUNG_BIT_MARK)) {
1012 return ERR;
1013 }
1014 offset++;
1015 if (MATCH_SPACE(results->rawbuf[offset], SAMSUNG_ONE_SPACE)) {
1016 data = (data << 1) | 1;
1017 }
1018 else if (MATCH_SPACE(results->rawbuf[offset], SAMSUNG_ZERO_SPACE)) {
1019 data <<= 1;
1020 }
1021 else {
1022 return ERR;
1023 }
1024 offset++;
1025 }
1026 // Success
1027 results->bits = SAMSUNG_BITS;
1028 results->value = data;
1029 results->decode_type = SAMSUNG;
1030 return DECODED;
1031 }
1032
1033 /* -----------------------------------------------------------------------
1034 * hashdecode - decode an arbitrary IR code.
1035 * Instead of decoding using a standard encoding scheme
1036 * (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value.
1037 *
1038 * The algorithm: look at the sequence of MARK signals, and see if each one
1039 * is shorter (0), the same length (1), or longer (2) than the previous.
1040 * Do the same with the SPACE signals. Hszh the resulting sequence of 0's,
1041 * 1's, and 2's to a 32-bit value. This will give a unique value for each
1042 * different code (probably), for most code systems.
1043 *
1044 * http://arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html
1045 */
1046
1047 // Compare two tick values, returning 0 if newval is shorter,
1048 // 1 if newval is equal, and 2 if newval is longer
1049 // Use a tolerance of 20%
1050 int IRrecv::compare(unsigned int oldval, unsigned int newval) {
1051 if (newval < oldval * .8) {
1052 return 0;
1053 }
1054 else if (oldval < newval * .8) {
1055 return 2;
1056 }
1057 else {
1058 return 1;
1059 }
1060 }
1061
1062 // Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param
1063 #define FNV_PRIME_32 16777619
1064 #define FNV_BASIS_32 2166136261
1065
1066 /* Converts the raw code values into a 32-bit hash code.
1067 * Hopefully this code is unique for each button.
1068 * This isn't a "real" decoding, just an arbitrary value.
1069 */
1070 long IRrecv::decodeHash(decode_results *results) {
1071 // Require at least 6 samples to prevent triggering on noise
1072 if (results->rawlen < 6) {
1073 return ERR;
1074 }
1075 long hash = FNV_BASIS_32;
1076 for (int i = 1; i+2 < results->rawlen; i++) {
1077 int value = compare(results->rawbuf[i], results->rawbuf[i+2]);
1078 // Add value into the hash
1079 hash = (hash * FNV_PRIME_32) ^ value;
1080 }
1081 results->value = hash;
1082 results->bits = 32;
1083 results->decode_type = UNKNOWN;
1084 return DECODED;
1085 }
1086
1087 /* Sharp and DISH support by Todd Treece ( http://unionbridge.org/design/ircommand )
1088
1089 The Dish send function needs to be repeated 4 times, and the Sharp function
1090 has the necessary repeat built in because of the need to invert the signal.
1091
1092 Sharp protocol documentation:
1093 http://www.sbprojects.com/knowledge/ir/sharp.htm
1094
1095 Here are the LIRC files that I found that seem to match the remote codes
1096 from the oscilloscope:
1097
1098 Sharp LCD TV:
1099 http://lirc.sourceforge.net/remotes/sharp/GA538WJSA
1100
1101 DISH NETWORK (echostar 301):
1102 http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx
1103
1104 For the DISH codes, only send the last for characters of the hex.
1105 i.e. use 0x1C10 instead of 0x0000000000001C10 which is listed in the
1106 linked LIRC file.
1107 */
1108
1109 void IRsend::sendSharpRaw(unsigned long data, int nbits) {
1110 enableIROut(38);
1111
1112 // Sending codes in bursts of 3 (normal, inverted, normal) makes transmission
1113 // much more reliable. That's the exact behaviour of CD-S6470 remote control.
1114 for (int n = 0; n < 3; n++) {
1115 for (int i = 1 << (nbits-1); i > 0; i>>=1) {
1116 if (data & i) {
1117 mark(SHARP_BIT_MARK);
1118 space(SHARP_ONE_SPACE);
1119 }
1120 else {
1121 mark(SHARP_BIT_MARK);
1122 space(SHARP_ZERO_SPACE);
1123 }
1124 }
1125
1126 mark(SHARP_BIT_MARK);
1127 space(SHARP_ZERO_SPACE);
1128 delay(40);
1129
1130 data = data ^ SHARP_TOGGLE_MASK;
1131 }
1132 }
1133
1134 // Sharp send compatible with data obtained through decodeSharp
1135 void IRsend::sendSharp(unsigned int address, unsigned int command) {
1136 sendSharpRaw((address << 10) | (command << 2) | 2, 15);
1137 }
1138
1139 void IRsend::sendDISH(unsigned long data, int nbits) {
1140 enableIROut(56);
1141 mark(DISH_HDR_MARK);
1142 space(DISH_HDR_SPACE);
1143 for (int i = 0; i < nbits; i++) {
1144 if (data & DISH_TOP_BIT) {
1145 mark(DISH_BIT_MARK);
1146 space(DISH_ONE_SPACE);
1147 }
1148 else {
1149 mark(DISH_BIT_MARK);
1150 space(DISH_ZERO_SPACE);
1151 }
1152 data <<= 1;
1153 }
1154 }