82 Commits
master ... BETA

Author SHA1 Message Date
Rafi Khan
2dbfee0c2e Added to changelog 2015-03-09 23:01:41 -06:00
Rafi Khan
49855488d5 Merge branch 'fab672000-master' into experimental
Conflicts:
	IRremote.cpp
	IRremote.h
* Saves lots of precious ram
* Debug Improvement
* Minor refactoring
* Better Install Instructions
* Using F() Macro

Credits: @zt30 and @fab672000.
Merged PR: #109
2015-03-09 22:55:22 -06:00
fab672000
e04e7d31b7 Debug Improvement:
Saved a lot of ram in debug mode by switching the constant strings to the flash memory space, see the F() macro changes.
Minor Improvement:
  Saved one byte of ram per class instantiation as decode_type attribute only needs to be int8_t so 8bits
2015-03-09 21:28:37 -05:00
Rafi Khan
c1c6bd4199 Added reference to GitHub page 2015-03-09 18:54:25 -06:00
Rafi Khan
0096727887 Fixed some syntax errors mentioned by @crash7 and also added Aiwa decoding to the changelog 2015-03-09 15:47:31 -06:00
Rafi Khan
2768ddc676 Releases can be found on the releases page. 2015-03-09 13:01:25 -06:00
Rafi Khan
74622ec776 Merge branch 'crash7-master' into experimental
Conflicts:
	IRremote.h
2015-03-08 21:12:08 -06:00
Rafi Khan
9a5d40a74c Changed define for Aiwa from 14 to 15 2015-03-08 21:09:48 -06:00
Rafi Khan
1cf65bbcde Merge branch 'master' of https://github.com/crash7/Arduino-IRremote into crash7-master 2015-03-08 21:07:53 -06:00
Rafi Khan
2926b33526 Fixed another mistake 2015-03-08 20:59:59 -06:00
Rafi Khan
ccc7ad9627 Fixed a mistake 2015-03-08 20:58:20 -06:00
Rafi Khan
7b08532e47 Moved contributors to a different file 2015-03-08 19:42:47 -06:00
Rafi Khan
3b16c12b59 Added Neco777 to contributors 2015-03-08 19:40:16 -06:00
Rafi Khan
50530b6519 Added changelog 2015-03-08 19:31:34 -06:00
Rafi Khan
095d8241f1 Change Version number 2015-03-08 19:23:50 -06:00
Rafi Khan
9c2064c5b4 add crash7 to contributors list 2015-03-08 17:38:20 -06:00
Rafi Khan
3256c847b2 remove index (for real) 2015-03-08 17:37:06 -06:00
Rafi Khan
2c6067eb30 Merge branch 'master' of https://github.com/shirriff/Arduino-IRremote 2015-03-08 17:35:45 -06:00
Rafi Khan
c35f7219dd removed index 2015-03-08 17:35:21 -06:00
Rafi Khan
18f5aa639b Added GitHub Page 2015-03-08 17:30:36 -06:00
Rafi Khan
a87d558b73 Merge pull request #90 from ivankravets/patch-1
PlatformIO Library Manager manifest file
2015-03-08 17:16:29 -06:00
Christian Musa
bed4cc5c97 Added Aiwa protocol (remote control RC-T501).
Added Aiwa protocol (remote control RC-T501) based on lirc file.
Updated IRrecvDump example, added SendDemo example (AiwaRCT501SendDemo).
2015-03-08 19:40:03 -03:00
Rafi Khan
c0446fd659 Fixed broken links 2015-03-08 16:07:40 -06:00
Rafi Khan
12f7ef1d28 Add contributors to readme 2015-03-08 16:03:41 -06:00
Rafi Khan
93c6e4af55 changed SHARP to 14 2015-03-08 00:05:16 -06:00
Rafi Khan
3722d6a0cb Merge branch 'Informatic-decodesharp' into experimental 2015-03-08 00:02:24 -06:00
Rafi Khan
14f4c7af77 Merging Sharp 2015-03-08 00:02:22 -06:00
Rafi Khan
9235051c6a Readme is branch independent 2015-03-07 23:33:59 -06:00
Rafi Khan
3dd4ff6f5f README is branch independent 2015-03-07 23:33:07 -06:00
Rafi Khan
32e3bf780f Merge branch 'experimental' of https://github.com/shirriff/Arduino-IRremote into experimental 2015-03-07 23:32:10 -06:00
Rafi Khan
806d3246f9 Readme 2015-03-07 23:31:31 -06:00
Rafi Khan
f0670efe86 changed readme 2015-03-07 23:28:01 -06:00
Rafi Khan
4610e7eb0e NEC_ONE_SPACE should actually be 1690 2015-03-07 18:10:22 -06:00
Rafi Khan
13f207d863 Merge pull request #102 from cltnschlosser/patch-1
Add LG keyword to keywords file from #102
Credits: @cltnschlosser
2015-03-07 17:32:52 -06:00
Rafi Khan
7c67cc5c59 Merge pull request #105 from fmeschia/master
Added Whynter A/C remote protocol from #105. 
Credits: @fmeschia
2015-03-07 17:31:21 -06:00
Rafi Khan
4fed49fca6 Fixed typo 2015-03-07 17:24:50 -06:00
Rafi Khan
9d94115974 Revamped README 2015-03-07 17:22:29 -06:00
Rafi Khan
b3e3ced302 Fix #41
Fixes #41 by implementing the solution by @canondale
2015-03-07 16:53:43 -06:00
Francesco Meschia
0fce321c94 Added Whynter A/C remote protocol
Tested with Whynter ARC-110WD
2015-02-06 21:29:56 -08:00
Colton Schlosser
02f206e19c Add LG keyword 2015-01-10 14:17:43 -06:00
joshua noble
a881523044 Merge pull request #22 from PaulStoffregen/master
Teensy 3.0 compatibility
2014-11-16 07:20:33 -08:00
Ivan Kravets
a3cdf402d7 Avoid trademark issues with library name
Added frameworks and platforms fields
2014-10-20 11:41:09 +03:00
Ivan Kravets
e947f0924e PlatformIO-based manifest file
Web: http://platformio.ikravets.com/#!/lib/show/Arduino-IRremote
Docs: http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html
2014-09-25 14:18:56 +03:00
joshua noble
f2dafe5030 Merge pull request #84 from Informatic/sendsharp
sendSharp cleanup and API change
2014-09-21 20:52:40 -07:00
Piotr Dobrowolski
b04b31232f Update keywords.txt 2014-09-17 23:21:54 +02:00
Piotr Dobrowolski
5719e7c00f sendSharp API change to make it compatible with decodeSharp 2014-09-17 22:34:41 +02:00
Piotr Dobrowolski
95f93e639e Cleanup sendSharp and fix reliability 2014-09-17 22:33:14 +02:00
joshua noble
24ba950f5c Merge pull request #73 from DaAwesomeP/master
Add delay to IRrecvDemo Loop preventing duplicates
2014-08-28 21:47:31 -07:00
P THE AWESOME
18591b037c Add delay to IRrecvDemo Loop preventing duplicates
Prevents duplicates in serial when button was only pressed once.
2014-08-04 16:19:07 -05:00
joshua noble
6c7e2e0f72 Merge pull request #69 from vk2tds/master
LG A/C remote protocol decoding
2014-07-10 09:30:01 -07:00
Darryl Smith
66c3b1f47c Updates for LG Air Conditioner Remote 2014-07-10 08:27:36 +10:00
vk2tds
0af9c5a9e9 Update IRremoteInt.h 2014-07-07 08:27:15 +10:00
joshua noble
3c89676bab Merge pull request #62 from sstefanov/master
Added Samsung protocol
2014-06-23 08:42:25 -07:00
joshua noble
fba55fb843 Merge pull request #31 from X-Y/master
Multiple definition of "MATCH" error when running IRtest
2014-06-08 11:18:32 -07:00
sstefanov
0de2d18bdb Added Samsung protocol 2014-05-23 12:20:39 +03:00
joshua noble
46b4e1084e Merge pull request #34 from joshuajnoble/master
adding Attiny84 for Arduino Tiny
2013-07-23 16:51:07 -07:00
Joshua Noble
e22a691164 updating timer interrupt name for Attiny84 2013-07-23 16:50:20 -07:00
Joshua Noble
a6bf23d71d adding Attiny84 2013-07-18 11:21:21 -07:00
Xun Yang
acc1b6b86e Fixed MATCH, MATCH_MARK, MATCH_SPACE when both IRremoteInt.h and IRremoteInt.h are included in sketch 2013-06-14 17:15:28 +02:00
PaulStoffregen
9ba6628f04 Add support for Teensy 3.0 2013-01-20 06:48:13 -08:00
Ken Shirriff
3f70ad2e4c Merge pull request #13 from TKJElectronics/master
Added support for Arduino Leonardo
2012-08-13 23:18:25 -07:00
Kristian Lauszus
107fa6cf4d Added support for Leonardo 2012-08-14 01:24:14 +02:00
Ken Shirriff
9dae9393f3 Update readme for 1.x
Improve download and installation instructions. Remove obsolete 0018 version instructions.
2012-08-08 09:05:39 -07:00
Ken Shirriff
e03a593847 mitra changes
Conflicts:
	IRremote.cpp
	IRremote.h
	IRremoteInt.h
	keywords.txt
2012-08-06 23:43:43 -07:00
Ken Shirriff
072b2c3db6 Merge branch 'master' of https://github.com/sEpt0r/Arduino-IRremote
Conflicts:
	IRremoteInt.h
2012-08-05 23:46:35 -07:00
Ken Shirriff
b25accfdd1 Merge pull request #11 from fpo/patch-1
Timer2 disable interrupt
2012-06-05 23:00:56 -07:00
Ken Shirriff
ade7cb6c29 Merge pull request #7 from TKJElectronics/master
Added panasonic and JVC protocol and updated the library for Arduino IDE 1.0
2012-06-05 23:00:07 -07:00
fpo
11a43ec5b6 i think that's the correct way. 2012-06-03 13:48:42 +03:00
Kristian Lauszus
937ce48832 Added support for ATmega2560 2012-03-21 21:31:41 +01:00
Kristian Lauszus
c48f817593 Set panasonic carrier frequency to 35 kHz 2012-03-20 22:21:16 +01:00
Vasiliy Marnopolskiy
a2af9e32a6 Support board with Atmega8 2012-02-14 00:56:34 +04:00
Kristian Lauszus
96eedde481 Added keywords 2012-02-08 18:15:48 +01:00
Kristian Lauszus
753e52efe7 Added panasonic and JVC protocol
Most work already done by zenwheel, but the sendPanasonic command
didn't work. Sending and decoding is confirmed to work with using both
the JVC and Panasonic protocol.
The library has also been updated to work with Arduino IDE 1.0.
2012-02-08 18:09:18 +01:00
Ken Shirriff
fb741e9893 Add wiki link 2011-05-05 22:28:58 -07:00
Ken
4131d5bbb6 Merge branch 'master' of https://github.com/toddtreece/Arduino-IRremote into toddtreece-master 2010-12-09 22:49:55 -08:00
Todd Treece
ccb4ac32c2 updated website info in documentation for sharp and dish support 2010-12-08 18:18:37 -05:00
Ken
2eb19be290 Support multiple devices and platforms.
Patched in changes from Paul Stoffregen (http://www.pjrc.com/teensy/td_libs_IRremote.html)
2010-11-17 19:19:25 -08:00
Ken
0fc224a81e Update readme. 2010-11-15 22:36:42 -08:00
Ken
114d8afe67 Add Test2.
This tests functionality using a pair of Arduinos.
2010-11-15 22:05:16 -08:00
Todd Treece
9bc832ec55 Updated Sharp protocol documentation 2010-09-20 15:35:29 -04:00
Ken Shirriff
31d80abc3f Fix CRLF issues.
Many problems happen with git due to some machines liking CRLF at the
end of lines, and others linking CR.  To try to straighten this out,
I'm using Unix-style LF (\n) as the line endings.  To make sure your
repository remains consistent, try:

$ git config --global core.autocrlf input

For details, see:
http://help.github.com/dealing-with-lineendings/
2010-05-15 15:21:48 -07:00
Ken Shirriff
da2a0d8f9d Add information on downloading from github. 2010-03-20 23:56:27 -07:00
18 changed files with 2708 additions and 1187 deletions

16
Contributors.md Normal file
View File

@@ -0,0 +1,16 @@
## Contributors
These are the active contributors of this project that you may contact if there is anything you need help with or if you have suggestions.
- [z3t0](https://github.com/z3t0) : Active Contributor and currently also the main contributor.
* Email: zetoslab@gmail.com
* Skype: polarised16
- [shirriff](https://github.com/shirriff) : Owner of repository and creator of library.
- [Informatic](https://github.com/Informatic) : Active contributor
- [fmeschia](https://github.com/fmeschia) : Active contributor
- [PaulStoffregen](https://github.com/paulstroffregen) : Active contributor
- [crash7](https://github.com/crash7) : Active contributor
- [Neco777](https://github.com/neco777) : Active contributor
Note: This list is being updated constantly so please let [z3t0](https://github.com/z3t0) know if you have been missed.

File diff suppressed because it is too large Load Diff

View File

@@ -1,101 +1,144 @@
/* /*
* IRremote * IRremote
* Version 0.1 July, 2009 * Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff * Copyright 2009 Ken Shirriff
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm http://arcfn.com * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm http://arcfn.com
* * Edited by Mitra to add new controller SANYO
* Interrupt code based on NECIRrcv by Joe Knapp *
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 * Interrupt code based on NECIRrcv by Joe Knapp
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
*/ * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
*
#ifndef IRremote_h * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
#define IRremote_h * LG added by Darryl Smith (based on the JVC protocol)
* Whynter A/C ARC-110WD added by Francesco Meschia
// The following are compile-time library options. */
// If you change them, recompile the library.
// If DEBUG is defined, a lot of debugging output will be printed during decoding. #ifndef IRremote_h
// TEST must be defined for the IRtest unittests to work. It will make some #define IRremote_h
// methods virtual, which will be slightly slower, which is why it is optional.
// #define DEBUG #if defined(ARDUINO) && ARDUINO >= 100
// #define TEST #include <Arduino.h>
#else
// Results returned from the decoder #include <WProgram.h>
class decode_results { #endif
public:
int decode_type; // NEC, SONY, RC5, UNKNOWN
unsigned long value; // Decoded value // The following are compile-time library options.
int bits; // Number of bits in decoded value // If you change them, recompile the library.
volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks // If DEBUG is defined, a lot of debugging output will be printed during decoding.
int rawlen; // Number of records in rawbuf. // TEST must be defined for the IRtest unittests to work. It will make some
}; // methods virtual, which will be slightly slower, which is why it is optional.
//#define DEBUG
// Values for decode_type // #define TEST
#define NEC 1
#define SONY 2 // Results returned from the decoder
#define RC5 3 class decode_results {
#define RC6 4 public:
#define DISH 5 int8_t decode_type; // NEC, SONY, RC5, UNKNOWN
#define SHARP 6 int8_t bits; // Number of bits in decoded value
#define UNKNOWN -1 unsigned long value; // Decoded value
// Decoded value for NEC when a repeat code is received union { // This is used for decoding Panasonic and Sharp data
#define REPEAT 0xffffffff unsigned int panasonicAddress;
unsigned int sharpAddress;
// main class for receiving IR };
class IRrecv
{ volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks
public: int rawlen; // Number of records in rawbuf.
IRrecv(int recvpin); };
void blink13(int blinkflag);
int decode(decode_results *results); // Values for decode_type
void enableIRIn(); #define NEC 1
void resume(); #define SONY 2
private: #define RC5 3
// These are called by decode #define RC6 4
int getRClevel(decode_results *results, int *offset, int *used, int t1); #define DISH 5
long decodeNEC(decode_results *results); #define SHARP 6
long decodeSony(decode_results *results); #define PANASONIC 7
long decodeRC5(decode_results *results); #define JVC 8
long decodeRC6(decode_results *results); #define SANYO 9
long decodeHash(decode_results *results); #define MITSUBISHI 10
int compare(unsigned int oldval, unsigned int newval); #define SAMSUNG 11
#define LG 12
} #define WHYNTER 13
; #define Sharp 14
#define AIWA_RC_T501 15
// Only used for testing; can remove virtual for shorter code #define UNKNOWN -1
#ifdef TEST
#define VIRTUAL virtual // Decoded value for NEC when a repeat code is received
#else #define REPEAT 0xffffffff
#define VIRTUAL
#endif // main class for receiving IR
class IRrecv
class IRsend {
{ public:
public: IRrecv(int recvpin);
IRsend() {} void blink13(int blinkflag);
void sendNEC(unsigned long data, int nbits); int decode(decode_results *results);
void sendSony(unsigned long data, int nbits); void enableIRIn();
void sendRaw(unsigned int buf[], int len, int hz); void resume();
void sendRC5(unsigned long data, int nbits); private:
void sendRC6(unsigned long data, int nbits); // These are called by decode
void sendDISH(unsigned long data, int nbits); int getRClevel(decode_results *results, int *offset, int *used, int t1);
void sendSharp(unsigned long data, int nbits); long decodeNEC(decode_results *results);
// private: long decodeSony(decode_results *results);
void enableIROut(int khz); long decodeSharp(decode_results *results);
VIRTUAL void mark(int usec); long decodeSanyo(decode_results *results);
VIRTUAL void space(int usec); long decodeMitsubishi(decode_results *results);
} long decodeRC5(decode_results *results);
; long decodeRC6(decode_results *results);
long decodePanasonic(decode_results *results);
// Some useful constants long decodeLG(decode_results *results);
long decodeJVC(decode_results *results);
#define USECPERTICK 50 // microseconds per clock interrupt tick long decodeSAMSUNG(decode_results *results);
#define RAWBUF 76 // Length of raw duration buffer long decodeWhynter(decode_results *results);
long decodeAiwaRCT501(decode_results *results);
// Marks tend to be 100us too long, and spaces 100us too short long decodeHash(decode_results *results);
// when received due to sensor lag. int compare(unsigned int oldval, unsigned int newval);
#define MARK_EXCESS 100
} ;
#endif
// Only used for testing; can remove virtual for shorter code
#ifdef TEST
#define VIRTUAL virtual
#else
#define VIRTUAL
#endif
class IRsend
{
public:
IRsend() {}
void sendWhynter(unsigned long data, int nbits);
void sendNEC(unsigned long data, int nbits);
void sendSony(unsigned long data, int nbits);
// Neither Sanyo nor Mitsubishi send is implemented yet
// void sendSanyo(unsigned long data, int nbits);
// void sendMitsubishi(unsigned long data, int nbits);
void sendRaw(unsigned int buf[], int len, int hz);
void sendRC5(unsigned long data, int nbits);
void sendRC6(unsigned long data, int nbits);
void sendDISH(unsigned long data, int nbits);
void sendSharp(unsigned int address, unsigned int command);
void sendSharpRaw(unsigned long data, int nbits);
void sendPanasonic(unsigned int address, unsigned long data);
void sendJVC(unsigned long data, int nbits, int repeat); // *Note instead of sending the REPEAT constant if you want the JVC repeat signal sent, send the original code value and change the repeat argument from 0 to 1. JVC protocol repeats by skipping the header NOT by sending a separate code value like NEC does.
void sendAiwaRCT501(int code);
// private:
void sendSAMSUNG(unsigned long data, int nbits);
void enableIROut(int khz);
VIRTUAL void mark(int usec);
VIRTUAL void space(int usec);
} ;
// Some useful constants
#define USECPERTICK 50 // microseconds per clock interrupt tick
#define RAWBUF 100 // Length of raw duration buffer
// Marks tend to be 100us too long, and spaces 100us too short
// when received due to sensor lag.
#define MARK_EXCESS 100
#endif

View File

@@ -1,129 +1,539 @@
/* /*
* IRremote * IRremote
* Version 0.1 July, 2009 * Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff * Copyright 2009 Ken Shirriff
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
* *
* Interrupt code based on NECIRrcv by Joe Knapp * Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 *
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ * Interrupt code based on NECIRrcv by Joe Knapp
*/ * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
#ifndef IRremoteint_h *
#define IRremoteint_h * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
* Whynter A/C ARC-110WD added by Francesco Meschia
#include <WProgram.h> */
#define CLKFUDGE 5 // fudge factor for clock interrupt overhead #ifndef IRremoteint_h
#define CLK 256 // max value for clock (timer 2) #define IRremoteint_h
#define PRESCALE 8 // timer2 clock prescale
#define SYSCLOCK 16000000 // main Arduino clock #if defined(ARDUINO) && ARDUINO >= 100
#define CLKSPERUSEC (SYSCLOCK/PRESCALE/1000000) // timer clocks per microsecond #include <Arduino.h>
#else
#define ERR 0 #include <WProgram.h>
#define DECODED 1 #endif
#define BLINKLED 13 // define which timer to use
//
// defines for setting and clearing register bits // Uncomment the timer you wish to use on your board. If you
#ifndef cbi // are using another library which uses timer2, you have options
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) // to switch IRremote to use a different timer.
#endif
#ifndef sbi // Arduino Mega
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#endif //#define IR_USE_TIMER1 // tx = pin 11
#define IR_USE_TIMER2 // tx = pin 9
// clock timer reset value //#define IR_USE_TIMER3 // tx = pin 5
#define INIT_TIMER_COUNT2 (CLK - USECPERTICK*CLKSPERUSEC + CLKFUDGE) //#define IR_USE_TIMER4 // tx = pin 6
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT2 //#define IR_USE_TIMER5 // tx = pin 46
// pulse parameters in usec // Teensy 1.0
#define NEC_HDR_MARK 9000 #elif defined(__AVR_AT90USB162__)
#define NEC_HDR_SPACE 4500 #define IR_USE_TIMER1 // tx = pin 17
#define NEC_BIT_MARK 560
#define NEC_ONE_SPACE 1600 // Teensy 2.0
#define NEC_ZERO_SPACE 560 #elif defined(__AVR_ATmega32U4__)
#define NEC_RPT_SPACE 2250 //#define IR_USE_TIMER1 // tx = pin 14
//#define IR_USE_TIMER3 // tx = pin 9
#define SONY_HDR_MARK 2400 #define IR_USE_TIMER4_HS // tx = pin 10
#define SONY_HDR_SPACE 600
#define SONY_ONE_MARK 1200 // Teensy 3.0
#define SONY_ZERO_MARK 600 #elif defined(__MK20DX128__)
#define SONY_RPT_LENGTH 45000 #define IR_USE_TIMER_CMT // tx = pin 5
#define RC5_T1 889 // Teensy++ 1.0 & 2.0
#define RC5_RPT_LENGTH 46000 #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
//#define IR_USE_TIMER1 // tx = pin 25
#define RC6_HDR_MARK 2666 #define IR_USE_TIMER2 // tx = pin 1
#define RC6_HDR_SPACE 889 //#define IR_USE_TIMER3 // tx = pin 16
#define RC6_T1 444
#define RC6_RPT_LENGTH 46000 // Sanguino
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define SHARP_BIT_MARK 245 //#define IR_USE_TIMER1 // tx = pin 13
#define SHARP_ONE_SPACE 1805 #define IR_USE_TIMER2 // tx = pin 14
#define SHARP_ZERO_SPACE 795
#define SHARP_GAP 600000 // Atmega8
#define SHARP_TOGGLE_MASK 0x3FF #elif defined(__AVR_ATmega8P__) || defined(__AVR_ATmega8__)
#define SHARP_RPT_SPACE 3000 #define IR_USE_TIMER1 // tx = pin 9
#define DISH_HDR_MARK 400 // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
#define DISH_HDR_SPACE 6100 #else
#define DISH_BIT_MARK 400 //#define IR_USE_TIMER1 // tx = pin 9
#define DISH_ONE_SPACE 1700 #define IR_USE_TIMER2 // tx = pin 3
#define DISH_ZERO_SPACE 2800 #endif
#define DISH_RPT_SPACE 6200
#define DISH_TOP_BIT 0x8000
#define SHARP_BITS 15 #ifdef F_CPU
#define DISH_BITS 16 #define SYSCLOCK F_CPU // main Arduino clock
#else
#define TOLERANCE 25 // percent tolerance in measurements #define SYSCLOCK 16000000 // main Arduino clock
#define LTOL (1.0 - TOLERANCE/100.) #endif
#define UTOL (1.0 + TOLERANCE/100.)
#define ERR 0
#define _GAP 5000 // Minimum map between transmissions #define DECODED 1
#define GAP_TICKS (_GAP/USECPERTICK)
#define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK)) // defines for setting and clearing register bits
#define TICKS_HIGH(us) (int) (((us)*UTOL/USECPERTICK + 1)) #ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#ifndef DEBUG #endif
#define MATCH(measured_ticks, desired_us) ((measured_ticks) >= TICKS_LOW(desired_us) && (measured_ticks) <= TICKS_HIGH(desired_us)) #ifndef sbi
#define MATCH_MARK(measured_ticks, desired_us) MATCH(measured_ticks, (desired_us) + MARK_EXCESS) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define MATCH_SPACE(measured_ticks, desired_us) MATCH((measured_ticks), (desired_us) - MARK_EXCESS) #endif
// Debugging versions are in IRremote.cpp
#endif // Pulse parms are *50-100 for the Mark and *50+100 for the space
// First MARK is the one after the long gap
// receiver states // pulse parameters in usec
#define STATE_IDLE 2 #define WHYNTER_HDR_MARK 2850
#define STATE_MARK 3 #define WHYNTER_HDR_SPACE 2850
#define STATE_SPACE 4 #define WHYNTER_BIT_MARK 750
#define STATE_STOP 5 #define WHYNTER_ONE_MARK 750
#define WHYNTER_ONE_SPACE 2150
// information for the interrupt handler #define WHYNTER_ZERO_MARK 750
typedef struct { #define WHYNTER_ZERO_SPACE 750
uint8_t recvpin; // pin for IR data from detector
uint8_t rcvstate; // state machine #define NEC_HDR_MARK 9000
uint8_t blinkflag; // TRUE to enable blinking of pin 13 on IR processing #define NEC_HDR_SPACE 4500
unsigned int timer; // state timer, counts 50uS ticks. #define NEC_BIT_MARK 560
unsigned int rawbuf[RAWBUF]; // raw data #define NEC_ONE_SPACE 1690
uint8_t rawlen; // counter of entries in rawbuf #define NEC_ZERO_SPACE 560
} #define NEC_RPT_SPACE 2250
irparams_t;
#define SONY_HDR_MARK 2400
// Defined in IRremote.cpp #define SONY_HDR_SPACE 600
extern volatile irparams_t irparams; #define SONY_ONE_MARK 1200
#define SONY_ZERO_MARK 600
// IR detector output is active low #define SONY_RPT_LENGTH 45000
#define MARK 0 #define SONY_DOUBLE_SPACE_USECS 500 // usually ssee 713 - not using ticks as get number wrapround
#define SPACE 1
// SA 8650B
#define TOPBIT 0x80000000 #define SANYO_HDR_MARK 3500 // seen range 3500
#define SANYO_HDR_SPACE 950 // seen 950
#define NEC_BITS 32 #define SANYO_ONE_MARK 2400 // seen 2400
#define SONY_BITS 12 #define SANYO_ZERO_MARK 700 // seen 700
#define MIN_RC5_SAMPLES 11 #define SANYO_DOUBLE_SPACE_USECS 800 // usually ssee 713 - not using ticks as get number wrapround
#define MIN_RC6_SAMPLES 1 #define SANYO_RPT_LENGTH 45000
#endif // Mitsubishi RM 75501
// 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
// #define MITSUBISHI_HDR_MARK 250 // seen range 3500
#define MITSUBISHI_HDR_SPACE 350 // 7*50+100
#define MITSUBISHI_ONE_MARK 1950 // 41*50-100
#define MITSUBISHI_ZERO_MARK 750 // 17*50-100
// #define MITSUBISHI_DOUBLE_SPACE_USECS 800 // usually ssee 713 - not using ticks as get number wrapround
// #define MITSUBISHI_RPT_LENGTH 45000
#define RC5_T1 889
#define RC5_RPT_LENGTH 46000
#define RC6_HDR_MARK 2666
#define RC6_HDR_SPACE 889
#define RC6_T1 444
#define RC6_RPT_LENGTH 46000
#define SHARP_BIT_MARK 245
#define SHARP_ONE_SPACE 1805
#define SHARP_ZERO_SPACE 795
#define SHARP_GAP 600000
#define SHARP_TOGGLE_MASK 0x3FF
#define SHARP_RPT_SPACE 950 // 40ms
#define DISH_HDR_MARK 400
#define DISH_HDR_SPACE 6100
#define DISH_BIT_MARK 400
#define DISH_ONE_SPACE 1700
#define DISH_ZERO_SPACE 2800
#define DISH_RPT_SPACE 6200
#define DISH_TOP_BIT 0x8000
#define PANASONIC_HDR_MARK 3502
#define PANASONIC_HDR_SPACE 1750
#define PANASONIC_BIT_MARK 502
#define PANASONIC_ONE_SPACE 1244
#define PANASONIC_ZERO_SPACE 400
#define JVC_HDR_MARK 8000
#define JVC_HDR_SPACE 4000
#define JVC_BIT_MARK 600
#define JVC_ONE_SPACE 1600
#define JVC_ZERO_SPACE 550
#define JVC_RPT_LENGTH 60000
#define LG_HDR_MARK 8000
#define LG_HDR_SPACE 4000
#define LG_BIT_MARK 600
#define LG_ONE_SPACE 1600
#define LG_ZERO_SPACE 550
#define LG_RPT_LENGTH 60000
#define SAMSUNG_HDR_MARK 5000
#define SAMSUNG_HDR_SPACE 5000
#define SAMSUNG_BIT_MARK 560
#define SAMSUNG_ONE_SPACE 1600
#define SAMSUNG_ZERO_SPACE 560
#define SAMSUNG_RPT_SPACE 2250
#define SHARP_BITS 15
#define DISH_BITS 16
// AIWA RC T501
// Lirc file http://lirc.sourceforge.net/remotes/aiwa/RC-T501
#define AIWA_RC_T501_HZ 38
#define AIWA_RC_T501_BITS 15
#define AIWA_RC_T501_PRE_BITS 26
#define AIWA_RC_T501_POST_BITS 1
#define AIWA_RC_T501_SUM_BITS AIWA_RC_T501_PRE_BITS+AIWA_RC_T501_BITS+AIWA_RC_T501_POST_BITS
#define AIWA_RC_T501_HDR_MARK 8800
#define AIWA_RC_T501_HDR_SPACE 4500
#define AIWA_RC_T501_BIT_MARK 500
#define AIWA_RC_T501_ONE_SPACE 600
#define AIWA_RC_T501_ZERO_SPACE 1700
#define TOLERANCE 25 // percent tolerance in measurements
#define LTOL (1.0 - TOLERANCE/100.)
#define UTOL (1.0 + TOLERANCE/100.)
#define _GAP 5000 // Minimum map between transmissions
#define GAP_TICKS (_GAP/USECPERTICK)
#define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK))
#define TICKS_HIGH(us) (int) (((us)*UTOL/USECPERTICK + 1))
// receiver states
#define STATE_IDLE 2
#define STATE_MARK 3
#define STATE_SPACE 4
#define STATE_STOP 5
// information for the interrupt handler
typedef struct {
uint8_t recvpin; // pin for IR data from detector
uint8_t rcvstate; // state machine
uint8_t blinkflag; // TRUE to enable blinking of pin 13 on IR processing
unsigned int timer; // state timer, counts 50uS ticks.
unsigned int rawbuf[RAWBUF]; // raw data
uint8_t rawlen; // counter of entries in rawbuf
}
irparams_t;
// Defined in IRremote.cpp
extern volatile irparams_t irparams;
// IR detector output is active low
#define MARK 0
#define SPACE 1
#define TOPBIT 0x80000000
#define NEC_BITS 32
#define SONY_BITS 12
#define SANYO_BITS 12
#define MITSUBISHI_BITS 16
#define MIN_RC5_SAMPLES 11
#define MIN_RC6_SAMPLES 1
#define PANASONIC_BITS 48
#define JVC_BITS 16
#define LG_BITS 28
#define SAMSUNG_BITS 32
#define WHYNTER_BITS 32
// defines for timer2 (8 bits)
#if defined(IR_USE_TIMER2)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR2A |= _BV(COM2B1))
#define TIMER_DISABLE_PWM (TCCR2A &= ~(_BV(COM2B1)))
#define TIMER_ENABLE_INTR (TIMSK2 = _BV(OCIE2A))
#define TIMER_DISABLE_INTR (TIMSK2 = 0)
#define TIMER_INTR_NAME TIMER2_COMPA_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint8_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR2A = _BV(WGM20); \
TCCR2B = _BV(WGM22) | _BV(CS20); \
OCR2A = pwmval; \
OCR2B = pwmval / 3; \
})
#define TIMER_COUNT_TOP (SYSCLOCK * USECPERTICK / 1000000)
#if (TIMER_COUNT_TOP < 256)
#define TIMER_CONFIG_NORMAL() ({ \
TCCR2A = _BV(WGM21); \
TCCR2B = _BV(CS20); \
OCR2A = TIMER_COUNT_TOP; \
TCNT2 = 0; \
})
#else
#define TIMER_CONFIG_NORMAL() ({ \
TCCR2A = _BV(WGM21); \
TCCR2B = _BV(CS21); \
OCR2A = TIMER_COUNT_TOP / 8; \
TCNT2 = 0; \
})
#endif
#if defined(CORE_OC2B_PIN)
#define TIMER_PWM_PIN CORE_OC2B_PIN /* Teensy */
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER_PWM_PIN 9 /* Arduino Mega */
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define TIMER_PWM_PIN 14 /* Sanguino */
#else
#define TIMER_PWM_PIN 3 /* Arduino Duemilanove, Diecimila, LilyPad, etc */
#endif
// defines for timer1 (16 bits)
#elif defined(IR_USE_TIMER1)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR1A |= _BV(COM1A1))
#define TIMER_DISABLE_PWM (TCCR1A &= ~(_BV(COM1A1)))
#if defined(__AVR_ATmega8P__) || defined(__AVR_ATmega8__)
#define TIMER_ENABLE_INTR (TIMSK = _BV(OCIE1A))
#define TIMER_DISABLE_INTR (TIMSK = 0)
#else
#define TIMER_ENABLE_INTR (TIMSK1 = _BV(OCIE1A))
#define TIMER_DISABLE_INTR (TIMSK1 = 0)
#endif
#define TIMER_INTR_NAME TIMER1_COMPA_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR1A = _BV(WGM11); \
TCCR1B = _BV(WGM13) | _BV(CS10); \
ICR1 = pwmval; \
OCR1A = pwmval / 3; \
})
#define TIMER_CONFIG_NORMAL() ({ \
TCCR1A = 0; \
TCCR1B = _BV(WGM12) | _BV(CS10); \
OCR1A = SYSCLOCK * USECPERTICK / 1000000; \
TCNT1 = 0; \
})
#if defined(CORE_OC1A_PIN)
#define TIMER_PWM_PIN CORE_OC1A_PIN /* Teensy */
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER_PWM_PIN 11 /* Arduino Mega */
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define TIMER_PWM_PIN 13 /* Sanguino */
#else
#define TIMER_PWM_PIN 9 /* Arduino Duemilanove, Diecimila, LilyPad, etc */
#endif
// defines for timer3 (16 bits)
#elif defined(IR_USE_TIMER3)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR3A |= _BV(COM3A1))
#define TIMER_DISABLE_PWM (TCCR3A &= ~(_BV(COM3A1)))
#define TIMER_ENABLE_INTR (TIMSK3 = _BV(OCIE3A))
#define TIMER_DISABLE_INTR (TIMSK3 = 0)
#define TIMER_INTR_NAME TIMER3_COMPA_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR3A = _BV(WGM31); \
TCCR3B = _BV(WGM33) | _BV(CS30); \
ICR3 = pwmval; \
OCR3A = pwmval / 3; \
})
#define TIMER_CONFIG_NORMAL() ({ \
TCCR3A = 0; \
TCCR3B = _BV(WGM32) | _BV(CS30); \
OCR3A = SYSCLOCK * USECPERTICK / 1000000; \
TCNT3 = 0; \
})
#if defined(CORE_OC3A_PIN)
#define TIMER_PWM_PIN CORE_OC3A_PIN /* Teensy */
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER_PWM_PIN 5 /* Arduino Mega */
#else
#error "Please add OC3A pin number here\n"
#endif
// defines for timer4 (10 bits, high speed option)
#elif defined(IR_USE_TIMER4_HS)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1))
#define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1)))
#define TIMER_ENABLE_INTR (TIMSK4 = _BV(TOIE4))
#define TIMER_DISABLE_INTR (TIMSK4 = 0)
#define TIMER_INTR_NAME TIMER4_OVF_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR4A = (1<<PWM4A); \
TCCR4B = _BV(CS40); \
TCCR4C = 0; \
TCCR4D = (1<<WGM40); \
TCCR4E = 0; \
TC4H = pwmval >> 8; \
OCR4C = pwmval; \
TC4H = (pwmval / 3) >> 8; \
OCR4A = (pwmval / 3) & 255; \
})
#define TIMER_CONFIG_NORMAL() ({ \
TCCR4A = 0; \
TCCR4B = _BV(CS40); \
TCCR4C = 0; \
TCCR4D = 0; \
TCCR4E = 0; \
TC4H = (SYSCLOCK * USECPERTICK / 1000000) >> 8; \
OCR4C = (SYSCLOCK * USECPERTICK / 1000000) & 255; \
TC4H = 0; \
TCNT4 = 0; \
})
#if defined(CORE_OC4A_PIN)
#define TIMER_PWM_PIN CORE_OC4A_PIN /* Teensy */
#elif defined(__AVR_ATmega32U4__)
#define TIMER_PWM_PIN 13 /* Leonardo */
#else
#error "Please add OC4A pin number here\n"
#endif
// defines for timer4 (16 bits)
#elif defined(IR_USE_TIMER4)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR4A |= _BV(COM4A1))
#define TIMER_DISABLE_PWM (TCCR4A &= ~(_BV(COM4A1)))
#define TIMER_ENABLE_INTR (TIMSK4 = _BV(OCIE4A))
#define TIMER_DISABLE_INTR (TIMSK4 = 0)
#define TIMER_INTR_NAME TIMER4_COMPA_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR4A = _BV(WGM41); \
TCCR4B = _BV(WGM43) | _BV(CS40); \
ICR4 = pwmval; \
OCR4A = pwmval / 3; \
})
#define TIMER_CONFIG_NORMAL() ({ \
TCCR4A = 0; \
TCCR4B = _BV(WGM42) | _BV(CS40); \
OCR4A = SYSCLOCK * USECPERTICK / 1000000; \
TCNT4 = 0; \
})
#if defined(CORE_OC4A_PIN)
#define TIMER_PWM_PIN CORE_OC4A_PIN
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER_PWM_PIN 6 /* Arduino Mega */
#else
#error "Please add OC4A pin number here\n"
#endif
// defines for timer5 (16 bits)
#elif defined(IR_USE_TIMER5)
#define TIMER_RESET
#define TIMER_ENABLE_PWM (TCCR5A |= _BV(COM5A1))
#define TIMER_DISABLE_PWM (TCCR5A &= ~(_BV(COM5A1)))
#define TIMER_ENABLE_INTR (TIMSK5 = _BV(OCIE5A))
#define TIMER_DISABLE_INTR (TIMSK5 = 0)
#define TIMER_INTR_NAME TIMER5_COMPA_vect
#define TIMER_CONFIG_KHZ(val) ({ \
const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR5A = _BV(WGM51); \
TCCR5B = _BV(WGM53) | _BV(CS50); \
ICR5 = pwmval; \
OCR5A = pwmval / 3; \
})
#define TIMER_CONFIG_NORMAL() ({ \
TCCR5A = 0; \
TCCR5B = _BV(WGM52) | _BV(CS50); \
OCR5A = SYSCLOCK * USECPERTICK / 1000000; \
TCNT5 = 0; \
})
#if defined(CORE_OC5A_PIN)
#define TIMER_PWM_PIN CORE_OC5A_PIN
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER_PWM_PIN 46 /* Arduino Mega */
#else
#error "Please add OC5A pin number here\n"
#endif
// defines for special carrier modulator timer
#elif defined(IR_USE_TIMER_CMT)
#define TIMER_RESET ({ \
uint8_t tmp = CMT_MSC; \
CMT_CMD2 = 30; \
})
#define TIMER_ENABLE_PWM CORE_PIN5_CONFIG = PORT_PCR_MUX(2)|PORT_PCR_DSE|PORT_PCR_SRE
#define TIMER_DISABLE_PWM CORE_PIN5_CONFIG = PORT_PCR_MUX(1)|PORT_PCR_DSE|PORT_PCR_SRE
#define TIMER_ENABLE_INTR NVIC_ENABLE_IRQ(IRQ_CMT)
#define TIMER_DISABLE_INTR NVIC_DISABLE_IRQ(IRQ_CMT)
#define TIMER_INTR_NAME cmt_isr
#ifdef ISR
#undef ISR
#endif
#define ISR(f) void f(void)
#if F_BUS == 48000000
#define CMT_PPS_VAL 5
#else
#define CMT_PPS_VAL 2
#endif
#define TIMER_CONFIG_KHZ(val) ({ \
SIM_SCGC4 |= SIM_SCGC4_CMT; \
SIM_SOPT2 |= SIM_SOPT2_PTD7PAD; \
CMT_PPS = CMT_PPS_VAL; \
CMT_CGH1 = 2667 / val; \
CMT_CGL1 = 5333 / val; \
CMT_CMD1 = 0; \
CMT_CMD2 = 30; \
CMT_CMD3 = 0; \
CMT_CMD4 = 0; \
CMT_OC = 0x60; \
CMT_MSC = 0x01; \
})
#define TIMER_CONFIG_NORMAL() ({ \
SIM_SCGC4 |= SIM_SCGC4_CMT; \
CMT_PPS = CMT_PPS_VAL; \
CMT_CGH1 = 1; \
CMT_CGL1 = 1; \
CMT_CMD1 = 0; \
CMT_CMD2 = 30; \
CMT_CMD3 = 0; \
CMT_CMD4 = 19; \
CMT_OC = 0; \
CMT_MSC = 0x03; \
})
#define TIMER_PWM_PIN 5
#else // unknown timer
#error "Internal code configuration error, no known IR_USE_TIMER# defined\n"
#endif
// defines for blinking the LED
#if defined(CORE_LED0_PIN)
#define BLINKLED CORE_LED0_PIN
#define BLINKLED_ON() (digitalWrite(CORE_LED0_PIN, HIGH))
#define BLINKLED_OFF() (digitalWrite(CORE_LED0_PIN, LOW))
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define BLINKLED 13
#define BLINKLED_ON() (PORTB |= B10000000)
#define BLINKLED_OFF() (PORTB &= B01111111)
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define BLINKLED 0
#define BLINKLED_ON() (PORTD |= B00000001)
#define BLINKLED_OFF() (PORTD &= B11111110)
#else
#define BLINKLED 13
#define BLINKLED_ON() (PORTB |= B00100000)
#define BLINKLED_OFF() (PORTB &= B11011111)
#endif
#endif

26
README.md Normal file
View File

@@ -0,0 +1,26 @@
# IRremote Arduino Library
This library enables you to send and receive using infra-red signals on an arduino.
Check [here](http://shirriff.github.io/Arduino-IRremote/) for tutorials and more information.
## Version - 1.01
## Installation
1. Navigate to the [Releases](https://github.com/shirriff/Arduino-IRremote/releases) page.
2. Download the latest release.
3. Extract the zip file
4. Move the "IRremote" folder that has been extracted to your libraries directory.
## Contributing
If you want to contribute to this project:
- Report bugs and errors
- Ask for enhancements
- Create issues and pull requests
- Tell other people about this library
## Contributors
Check [here](Contributors.md)
## Copyright
Copyright 2009-2012 Ken Shirriff

13
changelog.md Normal file
View File

@@ -0,0 +1,13 @@
# Change Log
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [1.0.1] - 2015-03-08
### Added
- Support for Sharp Decoding
- Support for Aiwa Decoding
- Changelog documentation
### Changed
- Improved memory management in debugging
- Use of F() macro saves RAM

View File

@@ -0,0 +1,25 @@
/*
* IRremote: IRsendDemo - demonstrates sending IR codes with IRsend
* An IR LED must be connected to Arduino PWM pin 3.
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
*/
#include "IRremote.h"
#define POWER 0x7F80
IRsend irsend;
void setup() {
Serial.begin(9600);
Serial.println("Arduino Ready");
}
void loop() {
if (Serial.read() != -1) {
irsend.sendAiwaRCT501(POWER);
delay(60); // Optional
}
}

View File

@@ -165,10 +165,3 @@ void loop() {
} }
lastButtonState = buttonState; lastButtonState = buttonState;
} }

View File

@@ -25,4 +25,5 @@ void loop() {
Serial.println(results.value, HEX); Serial.println(results.value, HEX);
irrecv.resume(); // Receive the next value irrecv.resume(); // Receive the next value
} }
} delay(100);
}

View File

@@ -4,6 +4,8 @@
* Version 0.1 July, 2009 * Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff * Copyright 2009 Ken Shirriff
* http://arcfn.com * http://arcfn.com
* JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
* LG added by Darryl Smith (based on the JVC protocol)
*/ */
#include <IRremote.h> #include <IRremote.h>
@@ -42,6 +44,29 @@ void dump(decode_results *results) {
else if (results->decode_type == RC6) { else if (results->decode_type == RC6) {
Serial.print("Decoded RC6: "); Serial.print("Decoded RC6: ");
} }
else if (results->decode_type == PANASONIC) {
Serial.print("Decoded PANASONIC - Address: ");
Serial.print(results->panasonicAddress,HEX);
Serial.print(" Value: ");
}
else if (results->decode_type == SHARP) {
Serial.print("Decoded SHARP - Address: ");
Serial.print(results->sharpAddress,HEX);
Serial.print(" Value: ");
}
else if (results->decode_type == LG) {
Serial.print("Decoded LG: ");
}
else if (results->decode_type == JVC) {
Serial.print("Decoded JVC: ");
}
else if (results->decode_type == AIWA_RC_T501) {
Serial.print("Decoded AIWA RC T501: ");
}
else if (results->decode_type == WHYNTER) {
Serial.print("Decoded Whynter: ");
}
Serial.print(results->value, HEX); Serial.print(results->value, HEX);
Serial.print(" ("); Serial.print(" (");
Serial.print(results->bits, DEC); Serial.print(results->bits, DEC);
@@ -69,4 +94,4 @@ void loop() {
dump(&results); dump(&results);
irrecv.resume(); // Receive the next value irrecv.resume(); // Receive the next value
} }
} }

View File

@@ -82,4 +82,4 @@ void loop() {
last = millis(); last = millis();
irrecv.resume(); // Receive the next value irrecv.resume(); // Receive the next value
} }
} }

View File

@@ -23,4 +23,3 @@ void loop() {
} }
} }
} }

View File

@@ -1,190 +1,190 @@
/* /*
* IRremote: IRtest unittest * IRremote: IRtest unittest
* Version 0.1 July, 2009 * Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff * Copyright 2009 Ken Shirriff
* http://arcfn.com * http://arcfn.com
* *
* Note: to run these tests, edit IRremote/IRremote.h to add "#define TEST" * Note: to run these tests, edit IRremote/IRremote.h to add "#define TEST"
* You must then recompile the library by removing IRremote.o and restarting * You must then recompile the library by removing IRremote.o and restarting
* the arduino IDE. * the arduino IDE.
*/ */
#include <IRremote.h> #include <IRremote.h>
#include <IRremoteInt.h> #include <IRremoteInt.h>
// Dumps out the decode_results structure. // Dumps out the decode_results structure.
// Call this after IRrecv::decode() // Call this after IRrecv::decode()
// void * to work around compiler issue // void * to work around compiler issue
//void dump(void *v) { //void dump(void *v) {
// decode_results *results = (decode_results *)v // decode_results *results = (decode_results *)v
void dump(decode_results *results) { void dump(decode_results *results) {
int count = results->rawlen; int count = results->rawlen;
if (results->decode_type == UNKNOWN) { if (results->decode_type == UNKNOWN) {
Serial.println("Could not decode message"); Serial.println("Could not decode message");
} }
else { else {
if (results->decode_type == NEC) { if (results->decode_type == NEC) {
Serial.print("Decoded NEC: "); Serial.print("Decoded NEC: ");
} }
else if (results->decode_type == SONY) { else if (results->decode_type == SONY) {
Serial.print("Decoded SONY: "); Serial.print("Decoded SONY: ");
} }
else if (results->decode_type == RC5) { else if (results->decode_type == RC5) {
Serial.print("Decoded RC5: "); Serial.print("Decoded RC5: ");
} }
else if (results->decode_type == RC6) { else if (results->decode_type == RC6) {
Serial.print("Decoded RC6: "); Serial.print("Decoded RC6: ");
} }
Serial.print(results->value, HEX); Serial.print(results->value, HEX);
Serial.print(" ("); Serial.print(" (");
Serial.print(results->bits, DEC); Serial.print(results->bits, DEC);
Serial.println(" bits)"); Serial.println(" bits)");
} }
Serial.print("Raw ("); Serial.print("Raw (");
Serial.print(count, DEC); Serial.print(count, DEC);
Serial.print("): "); Serial.print("): ");
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if ((i % 2) == 1) { if ((i % 2) == 1) {
Serial.print(results->rawbuf[i]*USECPERTICK, DEC); Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
} }
else { else {
Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC); Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
} }
Serial.print(" "); Serial.print(" ");
} }
Serial.println(""); Serial.println("");
} }
IRrecv irrecv(0); IRrecv irrecv(0);
decode_results results; decode_results results;
class IRsendDummy : class IRsendDummy :
public IRsend public IRsend
{ {
public: public:
// For testing, just log the marks/spaces // For testing, just log the marks/spaces
#define SENDLOG_LEN 128 #define SENDLOG_LEN 128
int sendlog[SENDLOG_LEN]; int sendlog[SENDLOG_LEN];
int sendlogcnt; int sendlogcnt;
IRsendDummy() : IRsendDummy() :
IRsend() { IRsend() {
} }
void reset() { void reset() {
sendlogcnt = 0; sendlogcnt = 0;
} }
void mark(int time) { void mark(int time) {
sendlog[sendlogcnt] = time; sendlog[sendlogcnt] = time;
if (sendlogcnt < SENDLOG_LEN) sendlogcnt++; if (sendlogcnt < SENDLOG_LEN) sendlogcnt++;
} }
void space(int time) { void space(int time) {
sendlog[sendlogcnt] = -time; sendlog[sendlogcnt] = -time;
if (sendlogcnt < SENDLOG_LEN) sendlogcnt++; if (sendlogcnt < SENDLOG_LEN) sendlogcnt++;
} }
// Copies the dummy buf into the interrupt buf // Copies the dummy buf into the interrupt buf
void useDummyBuf() { void useDummyBuf() {
int last = SPACE; int last = SPACE;
irparams.rcvstate = STATE_STOP; irparams.rcvstate = STATE_STOP;
irparams.rawlen = 1; // Skip the gap irparams.rawlen = 1; // Skip the gap
for (int i = 0 ; i < sendlogcnt; i++) { for (int i = 0 ; i < sendlogcnt; i++) {
if (sendlog[i] < 0) { if (sendlog[i] < 0) {
if (last == MARK) { if (last == MARK) {
// New space // New space
irparams.rawbuf[irparams.rawlen++] = (-sendlog[i] - MARK_EXCESS) / USECPERTICK; irparams.rawbuf[irparams.rawlen++] = (-sendlog[i] - MARK_EXCESS) / USECPERTICK;
last = SPACE; last = SPACE;
} }
else { else {
// More space // More space
irparams.rawbuf[irparams.rawlen - 1] += -sendlog[i] / USECPERTICK; irparams.rawbuf[irparams.rawlen - 1] += -sendlog[i] / USECPERTICK;
} }
} }
else if (sendlog[i] > 0) { else if (sendlog[i] > 0) {
if (last == SPACE) { if (last == SPACE) {
// New mark // New mark
irparams.rawbuf[irparams.rawlen++] = (sendlog[i] + MARK_EXCESS) / USECPERTICK; irparams.rawbuf[irparams.rawlen++] = (sendlog[i] + MARK_EXCESS) / USECPERTICK;
last = MARK; last = MARK;
} }
else { else {
// More mark // More mark
irparams.rawbuf[irparams.rawlen - 1] += sendlog[i] / USECPERTICK; irparams.rawbuf[irparams.rawlen - 1] += sendlog[i] / USECPERTICK;
} }
} }
} }
if (irparams.rawlen % 2) { if (irparams.rawlen % 2) {
irparams.rawlen--; // Remove trailing space irparams.rawlen--; // Remove trailing space
} }
} }
}; };
IRsendDummy irsenddummy; IRsendDummy irsenddummy;
void verify(unsigned long val, int bits, int type) { void verify(unsigned long val, int bits, int type) {
irsenddummy.useDummyBuf(); irsenddummy.useDummyBuf();
irrecv.decode(&results); irrecv.decode(&results);
Serial.print("Testing "); Serial.print("Testing ");
Serial.print(val, HEX); Serial.print(val, HEX);
if (results.value == val && results.bits == bits && results.decode_type == type) { if (results.value == val && results.bits == bits && results.decode_type == type) {
Serial.println(": OK"); Serial.println(": OK");
} }
else { else {
Serial.println(": Error"); Serial.println(": Error");
dump(&results); dump(&results);
} }
} }
void testNEC(unsigned long val, int bits) { void testNEC(unsigned long val, int bits) {
irsenddummy.reset(); irsenddummy.reset();
irsenddummy.sendNEC(val, bits); irsenddummy.sendNEC(val, bits);
verify(val, bits, NEC); verify(val, bits, NEC);
} }
void testSony(unsigned long val, int bits) { void testSony(unsigned long val, int bits) {
irsenddummy.reset(); irsenddummy.reset();
irsenddummy.sendSony(val, bits); irsenddummy.sendSony(val, bits);
verify(val, bits, SONY); verify(val, bits, SONY);
} }
void testRC5(unsigned long val, int bits) { void testRC5(unsigned long val, int bits) {
irsenddummy.reset(); irsenddummy.reset();
irsenddummy.sendRC5(val, bits); irsenddummy.sendRC5(val, bits);
verify(val, bits, RC5); verify(val, bits, RC5);
} }
void testRC6(unsigned long val, int bits) { void testRC6(unsigned long val, int bits) {
irsenddummy.reset(); irsenddummy.reset();
irsenddummy.sendRC6(val, bits); irsenddummy.sendRC6(val, bits);
verify(val, bits, RC6); verify(val, bits, RC6);
} }
void test() { void test() {
Serial.println("NEC tests"); Serial.println("NEC tests");
testNEC(0x00000000, 32); testNEC(0x00000000, 32);
testNEC(0xffffffff, 32); testNEC(0xffffffff, 32);
testNEC(0xaaaaaaaa, 32); testNEC(0xaaaaaaaa, 32);
testNEC(0x55555555, 32); testNEC(0x55555555, 32);
testNEC(0x12345678, 32); testNEC(0x12345678, 32);
Serial.println("Sony tests"); Serial.println("Sony tests");
testSony(0xfff, 12); testSony(0xfff, 12);
testSony(0x000, 12); testSony(0x000, 12);
testSony(0xaaa, 12); testSony(0xaaa, 12);
testSony(0x555, 12); testSony(0x555, 12);
testSony(0x123, 12); testSony(0x123, 12);
Serial.println("RC5 tests"); Serial.println("RC5 tests");
testRC5(0xfff, 12); testRC5(0xfff, 12);
testRC5(0x000, 12); testRC5(0x000, 12);
testRC5(0xaaa, 12); testRC5(0xaaa, 12);
testRC5(0x555, 12); testRC5(0x555, 12);
testRC5(0x123, 12); testRC5(0x123, 12);
Serial.println("RC6 tests"); Serial.println("RC6 tests");
testRC6(0xfffff, 20); testRC6(0xfffff, 20);
testRC6(0x00000, 20); testRC6(0x00000, 20);
testRC6(0xaaaaa, 20); testRC6(0xaaaaa, 20);
testRC6(0x55555, 20); testRC6(0x55555, 20);
testRC6(0x12345, 20); testRC6(0x12345, 20);
} }
void setup() void setup()
{ {
Serial.begin(9600); Serial.begin(9600);
test(); test();
} }
void loop() { void loop() {
} }

View File

@@ -0,0 +1,290 @@
/*
* Test send/receive functions of IRremote, using a pair of Arduinos.
*
* Arduino #1 should have an IR LED connected to the send pin (3).
* Arduino #2 should have an IR detector/demodulator connected to the
* receive pin (11) and a visible LED connected to pin 3.
*
* The cycle:
* Arduino #1 will wait 2 seconds, then run through the tests.
* It repeats this forever.
* Arduino #2 will wait for at least one second of no signal
* (to synchronize with #1). It will then wait for the same test
* signals. It will log all the status to the serial port. It will
* also indicate status through the LED, which will flash each time a test
* is completed. If there is an error, it will light up for 5 seconds.
*
* The test passes if the LED flashes 19 times, pauses, and then repeats.
* The test fails if the LED lights for 5 seconds.
*
* The test software automatically decides which board is the sender and which is
* the receiver by looking for an input on the send pin, which will indicate
* the sender. You should hook the serial port to the receiver for debugging.
*
* Copyright 2010 Ken Shirriff
* http://arcfn.com
*/
#include <IRremote.h>
int RECV_PIN = 11;
int LED_PIN = 3;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;
#define RECEIVER 1
#define SENDER 2
#define ERROR 3
int mode;
void setup()
{
Serial.begin(9600);
// Check RECV_PIN to decide if we're RECEIVER or SENDER
if (digitalRead(RECV_PIN) == HIGH) {
mode = RECEIVER;
irrecv.enableIRIn();
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
Serial.println("Receiver mode");
}
else {
mode = SENDER;
Serial.println("Sender mode");
}
}
// Wait for the gap between tests, to synchronize with
// the sender.
// Specifically, wait for a signal followed by a gap of at last gap ms.
void waitForGap(int gap) {
Serial.println("Waiting for gap");
while (1) {
while (digitalRead(RECV_PIN) == LOW) {
}
unsigned long time = millis();
while (digitalRead(RECV_PIN) == HIGH) {
if (millis() - time > gap) {
return;
}
}
}
}
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
void dump(decode_results *results) {
int count = results->rawlen;
if (results->decode_type == UNKNOWN) {
Serial.println("Could not decode message");
}
else {
if (results->decode_type == NEC) {
Serial.print("Decoded NEC: ");
}
else if (results->decode_type == SONY) {
Serial.print("Decoded SONY: ");
}
else if (results->decode_type == RC5) {
Serial.print("Decoded RC5: ");
}
else if (results->decode_type == RC6) {
Serial.print("Decoded RC6: ");
}
Serial.print(results->value, HEX);
Serial.print(" (");
Serial.print(results->bits, DEC);
Serial.println(" bits)");
}
Serial.print("Raw (");
Serial.print(count, DEC);
Serial.print("): ");
for (int i = 0; i < count; i++) {
if ((i % 2) == 1) {
Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
}
else {
Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
}
Serial.print(" ");
}
Serial.println("");
}
// Test send or receive.
// If mode is SENDER, send a code of the specified type, value, and bits
// If mode is RECEIVER, receive a code and verify that it is of the
// specified type, value, and bits. For success, the LED is flashed;
// for failure, the mode is set to ERROR.
// The motivation behind this method is that the sender and the receiver
// can do the same test calls, and the mode variable indicates whether
// to send or receive.
void test(char *label, int type, unsigned long value, int bits) {
if (mode == SENDER) {
Serial.println(label);
if (type == NEC) {
irsend.sendNEC(value, bits);
}
else if (type == SONY) {
irsend.sendSony(value, bits);
}
else if (type == RC5) {
irsend.sendRC5(value, bits);
}
else if (type == RC6) {
irsend.sendRC6(value, bits);
}
else {
Serial.print(label);
Serial.println("Bad type!");
}
delay(200);
}
else if (mode == RECEIVER) {
irrecv.resume(); // Receive the next value
unsigned long max_time = millis() + 30000;
Serial.print(label);
// Wait for decode or timeout
while (!irrecv.decode(&results)) {
if (millis() > max_time) {
Serial.println("Timeout receiving data");
mode = ERROR;
return;
}
}
if (type == results.decode_type && value == results.value && bits == results.bits) {
Serial.println (": OK");
digitalWrite(LED_PIN, HIGH);
delay(20);
digitalWrite(LED_PIN, LOW);
}
else {
Serial.println(": BAD");
dump(&results);
mode = ERROR;
}
}
}
// Test raw send or receive. This is similar to the test method,
// except it send/receives raw data.
void testRaw(char *label, unsigned int *rawbuf, int rawlen) {
if (mode == SENDER) {
Serial.println(label);
irsend.sendRaw(rawbuf, rawlen, 38 /* kHz */);
delay(200);
}
else if (mode == RECEIVER ) {
irrecv.resume(); // Receive the next value
unsigned long max_time = millis() + 30000;
Serial.print(label);
// Wait for decode or timeout
while (!irrecv.decode(&results)) {
if (millis() > max_time) {
Serial.println("Timeout receiving data");
mode = ERROR;
return;
}
}
// Received length has extra first element for gap
if (rawlen != results.rawlen - 1) {
Serial.print("Bad raw length ");
Serial.println(results.rawlen, DEC);
mode = ERROR;
return;
}
for (int i = 0; i < rawlen; i++) {
long got = results.rawbuf[i+1] * USECPERTICK;
// Adjust for extra duration of marks
if (i % 2 == 0) {
got -= MARK_EXCESS;
}
else {
got += MARK_EXCESS;
}
// See if close enough, within 25%
if (rawbuf[i] * 1.25 < got || got * 1.25 < rawbuf[i]) {
Serial.println(": BAD");
dump(&results);
mode = ERROR;
return;
}
}
Serial.println (": OK");
digitalWrite(LED_PIN, HIGH);
delay(20);
digitalWrite(LED_PIN, LOW);
}
}
// This is the raw data corresponding to NEC 0x12345678
unsigned int sendbuf[] = { /* NEC format */
9000, 4500,
560, 560, 560, 560, 560, 560, 560, 1690, /* 1 */
560, 560, 560, 560, 560, 1690, 560, 560, /* 2 */
560, 560, 560, 560, 560, 1690, 560, 1690, /* 3 */
560, 560, 560, 1690, 560, 560, 560, 560, /* 4 */
560, 560, 560, 1690, 560, 560, 560, 1690, /* 5 */
560, 560, 560, 1690, 560, 1690, 560, 560, /* 6 */
560, 560, 560, 1690, 560, 1690, 560, 1690, /* 7 */
560, 1690, 560, 560, 560, 560, 560, 560, /* 8 */
560};
void loop() {
if (mode == SENDER) {
delay(2000); // Delay for more than gap to give receiver a better chance to sync.
}
else if (mode == RECEIVER) {
waitForGap(1000);
}
else if (mode == ERROR) {
// Light up for 5 seconds for error
digitalWrite(LED_PIN, HIGH);
delay(5000);
digitalWrite(LED_PIN, LOW);
mode = RECEIVER; // Try again
return;
}
// The test suite.
test("SONY1", SONY, 0x123, 12);
test("SONY2", SONY, 0x000, 12);
test("SONY3", SONY, 0xfff, 12);
test("SONY4", SONY, 0x12345, 20);
test("SONY5", SONY, 0x00000, 20);
test("SONY6", SONY, 0xfffff, 20);
test("NEC1", NEC, 0x12345678, 32);
test("NEC2", NEC, 0x00000000, 32);
test("NEC3", NEC, 0xffffffff, 32);
test("NEC4", NEC, REPEAT, 32);
test("RC51", RC5, 0x12345678, 32);
test("RC52", RC5, 0x0, 32);
test("RC53", RC5, 0xffffffff, 32);
test("RC61", RC6, 0x12345678, 32);
test("RC62", RC6, 0x0, 32);
test("RC63", RC6, 0xffffffff, 32);
// Tests of raw sending and receiving.
// First test sending raw and receiving raw.
// Then test sending raw and receiving decoded NEC
// Then test sending NEC and receiving raw
testRaw("RAW1", sendbuf, 67);
if (mode == SENDER) {
testRaw("RAW2", sendbuf, 67);
test("RAW3", NEC, 0x12345678, 32);
}
else {
test("RAW2", NEC, 0x12345678, 32);
testRaw("RAW3", sendbuf, 67);
}
}

View File

@@ -0,0 +1,29 @@
/*
* IRremote: IRsendDemo - demonstrates sending IR codes with IRsend
* An IR LED must be connected to Arduino PWM pin 3.
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
* JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
*/
#include <IRremote.h>
#define PanasonicAddress 0x4004 // Panasonic address (Pre data)
#define PanasonicPower 0x100BCBD // Panasonic Power button
#define JVCPower 0xC5E8
IRsend irsend;
void setup()
{
}
void loop() {
irsend.sendPanasonic(PanasonicAddress,PanasonicPower); // This should turn your TV on and off
irsend.sendJVC(JVCPower, 16,0); // hex value, 16 bits, no repeat
delayMicroseconds(50); // see http://www.sbprojects.com/knowledge/ir/jvc.php for information
irsend.sendJVC(JVCPower, 16,1); // hex value, 16 bits, repeat
delayMicroseconds(50);
}

View File

@@ -6,32 +6,48 @@
# Datatypes (KEYWORD1) # Datatypes (KEYWORD1)
####################################### #######################################
decode_results KEYWORD1 decode_results KEYWORD1
IRrecv KEYWORD1 IRrecv KEYWORD1
IRsend KEYWORD1 IRsend KEYWORD1
####################################### #######################################
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)
####################################### #######################################
blink13 KEYWORD2 blink13 KEYWORD2
decode KEYWORD2 decode KEYWORD2
enableIRIn KEYWORD2 enableIRIn KEYWORD2
resume KEYWORD2 resume KEYWORD2
enableIROut KEYWORD2 enableIROut KEYWORD2
sendNEC KEYWORD2 sendNEC KEYWORD2
sendSony KEYWORD2 sendSony KEYWORD2
sendRaw KEYWORD2 sendSanyo KEYWORD2
sendRC5 KEYWORD2 sendMitsubishi KEYWORD2
sendRC6 KEYWORD2 sendRaw KEYWORD2
sendRC5 KEYWORD2
sendRC6 KEYWORD2
sendDISH KEYWORD2
sendSharp KEYWORD2
sendSharpRaw KEYWORD2
sendPanasonic KEYWORD2
sendJVC KEYWORD2
# #
####################################### #######################################
# Constants (LITERAL1) # Constants (LITERAL1)
####################################### #######################################
NEC LITERAL1 NEC LITERAL1
SONY LITERAL1 SONY LITERAL1
RC5 LITERAL1 SANYO LITERAL1
RC6 LITERAL1 MITSUBISHI LITERAL1
UNKNOWN LITERAL1 RC5 LITERAL1
REPEAT LITERAL1 RC6 LITERAL1
DISH LITERAL1
SHARP LITERAL1
PANASONIC LITERAL1
JVC LITERAL1
LG LITERAL1
SHARP LITERAL1
UNKNOWN LITERAL1
REPEAT LITERAL1

12
library.json Normal file
View File

@@ -0,0 +1,12 @@
{
"name": "IRremote",
"keywords": "infrared, ir, remote",
"description": "Send and receive infrared signals with multiple protocols",
"repository":
{
"type": "git",
"url": "https://github.com/shirriff/Arduino-IRremote.git"
},
"frameworks": "arduino",
"platforms": "atmelavr"
}

11
readme
View File

@@ -1,11 +0,0 @@
This is the IRremote library for the Arduino.
To install, move this directory to:
arduino-00nn/hardware/libraries/IRremote
I.e. after installation you should have files such as:
arduino-00nn/hardware/libraries/IRremote/IRremote.cpp
For details see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
Copyright 2009 Ken Shirriff