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
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm http://arcfn.com
*
* 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 IRremote_h
#define IRremote_h
// 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.
// 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
// #define TEST
// Results returned from the decoder
class decode_results {
public:
int decode_type; // NEC, SONY, RC5, UNKNOWN
unsigned long value; // Decoded value
int bits; // Number of bits in decoded value
volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks
int rawlen; // Number of records in rawbuf.
};
// Values for decode_type
#define NEC 1
#define SONY 2
#define RC5 3
#define RC6 4
#define DISH 5
#define SHARP 6
#define UNKNOWN -1
// Decoded value for NEC when a repeat code is received
#define REPEAT 0xffffffff
// main class for receiving IR
class IRrecv
{
public:
IRrecv(int recvpin);
void blink13(int blinkflag);
int decode(decode_results *results);
void enableIRIn();
void resume();
private:
// These are called by decode
int getRClevel(decode_results *results, int *offset, int *used, int t1);
long decodeNEC(decode_results *results);
long decodeSony(decode_results *results);
long decodeRC5(decode_results *results);
long decodeRC6(decode_results *results);
long decodeHash(decode_results *results);
int compare(unsigned int oldval, unsigned int newval);
}
;
// Only used for testing; can remove virtual for shorter code
#ifdef TEST
#define VIRTUAL virtual
#else
#define VIRTUAL
#endif
class IRsend
{
public:
IRsend() {}
void sendNEC(unsigned long data, int nbits);
void sendSony(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 long data, int nbits);
// private:
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 76 // 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
/*
* IRremote
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* 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
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
*
* 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)
* Whynter A/C ARC-110WD added by Francesco Meschia
*/
#ifndef IRremote_h
#define IRremote_h
#if defined(ARDUINO) && ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
// 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.
// 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
// #define TEST
// Results returned from the decoder
class decode_results {
public:
int8_t decode_type; // NEC, SONY, RC5, UNKNOWN
int8_t bits; // Number of bits in decoded value
unsigned long value; // Decoded value
union { // This is used for decoding Panasonic and Sharp data
unsigned int panasonicAddress;
unsigned int sharpAddress;
};
volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks
int rawlen; // Number of records in rawbuf.
};
// Values for decode_type
#define NEC 1
#define SONY 2
#define RC5 3
#define RC6 4
#define DISH 5
#define SHARP 6
#define PANASONIC 7
#define JVC 8
#define SANYO 9
#define MITSUBISHI 10
#define SAMSUNG 11
#define LG 12
#define WHYNTER 13
#define Sharp 14
#define AIWA_RC_T501 15
#define UNKNOWN -1
// Decoded value for NEC when a repeat code is received
#define REPEAT 0xffffffff
// main class for receiving IR
class IRrecv
{
public:
IRrecv(int recvpin);
void blink13(int blinkflag);
int decode(decode_results *results);
void enableIRIn();
void resume();
private:
// These are called by decode
int getRClevel(decode_results *results, int *offset, int *used, int t1);
long decodeNEC(decode_results *results);
long decodeSony(decode_results *results);
long decodeSharp(decode_results *results);
long decodeSanyo(decode_results *results);
long decodeMitsubishi(decode_results *results);
long decodeRC5(decode_results *results);
long decodeRC6(decode_results *results);
long decodePanasonic(decode_results *results);
long decodeLG(decode_results *results);
long decodeJVC(decode_results *results);
long decodeSAMSUNG(decode_results *results);
long decodeWhynter(decode_results *results);
long decodeAiwaRCT501(decode_results *results);
long decodeHash(decode_results *results);
int compare(unsigned int oldval, unsigned int newval);
} ;
// 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
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
*
* 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
#include <WProgram.h>
#define CLKFUDGE 5 // fudge factor for clock interrupt overhead
#define CLK 256 // max value for clock (timer 2)
#define PRESCALE 8 // timer2 clock prescale
#define SYSCLOCK 16000000 // main Arduino clock
#define CLKSPERUSEC (SYSCLOCK/PRESCALE/1000000) // timer clocks per microsecond
#define ERR 0
#define DECODED 1
#define BLINKLED 13
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// clock timer reset value
#define INIT_TIMER_COUNT2 (CLK - USECPERTICK*CLKSPERUSEC + CLKFUDGE)
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT2
// pulse parameters in usec
#define NEC_HDR_MARK 9000
#define NEC_HDR_SPACE 4500
#define NEC_BIT_MARK 560
#define NEC_ONE_SPACE 1600
#define NEC_ZERO_SPACE 560
#define NEC_RPT_SPACE 2250
#define SONY_HDR_MARK 2400
#define SONY_HDR_SPACE 600
#define SONY_ONE_MARK 1200
#define SONY_ZERO_MARK 600
#define SONY_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 3000
#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 SHARP_BITS 15
#define DISH_BITS 16
#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))
#ifndef DEBUG
#define MATCH(measured_ticks, desired_us) ((measured_ticks) >= TICKS_LOW(desired_us) && (measured_ticks) <= TICKS_HIGH(desired_us))
#define MATCH_MARK(measured_ticks, desired_us) MATCH(measured_ticks, (desired_us) + MARK_EXCESS)
#define MATCH_SPACE(measured_ticks, desired_us) MATCH((measured_ticks), (desired_us) - MARK_EXCESS)
// Debugging versions are in IRremote.cpp
#endif
// 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 MIN_RC5_SAMPLES 11
#define MIN_RC6_SAMPLES 1
#endif
/*
* IRremote
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
*
* Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
*
* 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/
*
* 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
*/
#ifndef IRremoteint_h
#define IRremoteint_h
#if defined(ARDUINO) && ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
// define which timer to use
//
// Uncomment the timer you wish to use on your board. If you
// are using another library which uses timer2, you have options
// to switch IRremote to use a different timer.
// Arduino Mega
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//#define IR_USE_TIMER1 // tx = pin 11
#define IR_USE_TIMER2 // tx = pin 9
//#define IR_USE_TIMER3 // tx = pin 5
//#define IR_USE_TIMER4 // tx = pin 6
//#define IR_USE_TIMER5 // tx = pin 46
// Teensy 1.0
#elif defined(__AVR_AT90USB162__)
#define IR_USE_TIMER1 // tx = pin 17
// Teensy 2.0
#elif defined(__AVR_ATmega32U4__)
//#define IR_USE_TIMER1 // tx = pin 14
//#define IR_USE_TIMER3 // tx = pin 9
#define IR_USE_TIMER4_HS // tx = pin 10
// Teensy 3.0
#elif defined(__MK20DX128__)
#define IR_USE_TIMER_CMT // tx = pin 5
// Teensy++ 1.0 & 2.0
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
//#define IR_USE_TIMER1 // tx = pin 25
#define IR_USE_TIMER2 // tx = pin 1
//#define IR_USE_TIMER3 // tx = pin 16
// Sanguino
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
//#define IR_USE_TIMER1 // tx = pin 13
#define IR_USE_TIMER2 // tx = pin 14
// Atmega8
#elif defined(__AVR_ATmega8P__) || defined(__AVR_ATmega8__)
#define IR_USE_TIMER1 // tx = pin 9
// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
#else
//#define IR_USE_TIMER1 // tx = pin 9
#define IR_USE_TIMER2 // tx = pin 3
#endif
#ifdef F_CPU
#define SYSCLOCK F_CPU // main Arduino clock
#else
#define SYSCLOCK 16000000 // main Arduino clock
#endif
#define ERR 0
#define DECODED 1
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// Pulse parms are *50-100 for the Mark and *50+100 for the space
// First MARK is the one after the long gap
// pulse parameters in usec
#define WHYNTER_HDR_MARK 2850
#define WHYNTER_HDR_SPACE 2850
#define WHYNTER_BIT_MARK 750
#define WHYNTER_ONE_MARK 750
#define WHYNTER_ONE_SPACE 2150
#define WHYNTER_ZERO_MARK 750
#define WHYNTER_ZERO_SPACE 750
#define NEC_HDR_MARK 9000
#define NEC_HDR_SPACE 4500
#define NEC_BIT_MARK 560
#define NEC_ONE_SPACE 1690
#define NEC_ZERO_SPACE 560
#define NEC_RPT_SPACE 2250
#define SONY_HDR_MARK 2400
#define SONY_HDR_SPACE 600
#define SONY_ONE_MARK 1200
#define SONY_ZERO_MARK 600
#define SONY_RPT_LENGTH 45000
#define SONY_DOUBLE_SPACE_USECS 500 // usually ssee 713 - not using ticks as get number wrapround
// SA 8650B
#define SANYO_HDR_MARK 3500 // seen range 3500
#define SANYO_HDR_SPACE 950 // seen 950
#define SANYO_ONE_MARK 2400 // seen 2400
#define SANYO_ZERO_MARK 700 // seen 700
#define SANYO_DOUBLE_SPACE_USECS 800 // usually ssee 713 - not using ticks as get number wrapround
#define SANYO_RPT_LENGTH 45000
// 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;
}

View File

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

View File

@@ -4,6 +4,8 @@
* 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)
* LG added by Darryl Smith (based on the JVC protocol)
*/
#include <IRremote.h>
@@ -42,6 +44,29 @@ void dump(decode_results *results) {
else if (results->decode_type == 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(" (");
Serial.print(results->bits, DEC);
@@ -69,4 +94,4 @@ void loop() {
dump(&results);
irrecv.resume(); // Receive the next value
}
}
}

View File

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

View File

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

View File

@@ -1,190 +1,190 @@
/*
* IRremote: IRtest unittest
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
*
* 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
* the arduino IDE.
*/
#include <IRremote.h>
#include <IRremoteInt.h>
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
// decode_results *results = (decode_results *)v
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("");
}
IRrecv irrecv(0);
decode_results results;
class IRsendDummy :
public IRsend
{
public:
// For testing, just log the marks/spaces
#define SENDLOG_LEN 128
int sendlog[SENDLOG_LEN];
int sendlogcnt;
IRsendDummy() :
IRsend() {
}
void reset() {
sendlogcnt = 0;
}
void mark(int time) {
sendlog[sendlogcnt] = time;
if (sendlogcnt < SENDLOG_LEN) sendlogcnt++;
}
void space(int time) {
sendlog[sendlogcnt] = -time;
if (sendlogcnt < SENDLOG_LEN) sendlogcnt++;
}
// Copies the dummy buf into the interrupt buf
void useDummyBuf() {
int last = SPACE;
irparams.rcvstate = STATE_STOP;
irparams.rawlen = 1; // Skip the gap
for (int i = 0 ; i < sendlogcnt; i++) {
if (sendlog[i] < 0) {
if (last == MARK) {
// New space
irparams.rawbuf[irparams.rawlen++] = (-sendlog[i] - MARK_EXCESS) / USECPERTICK;
last = SPACE;
}
else {
// More space
irparams.rawbuf[irparams.rawlen - 1] += -sendlog[i] / USECPERTICK;
}
}
else if (sendlog[i] > 0) {
if (last == SPACE) {
// New mark
irparams.rawbuf[irparams.rawlen++] = (sendlog[i] + MARK_EXCESS) / USECPERTICK;
last = MARK;
}
else {
// More mark
irparams.rawbuf[irparams.rawlen - 1] += sendlog[i] / USECPERTICK;
}
}
}
if (irparams.rawlen % 2) {
irparams.rawlen--; // Remove trailing space
}
}
};
IRsendDummy irsenddummy;
void verify(unsigned long val, int bits, int type) {
irsenddummy.useDummyBuf();
irrecv.decode(&results);
Serial.print("Testing ");
Serial.print(val, HEX);
if (results.value == val && results.bits == bits && results.decode_type == type) {
Serial.println(": OK");
}
else {
Serial.println(": Error");
dump(&results);
}
}
void testNEC(unsigned long val, int bits) {
irsenddummy.reset();
irsenddummy.sendNEC(val, bits);
verify(val, bits, NEC);
}
void testSony(unsigned long val, int bits) {
irsenddummy.reset();
irsenddummy.sendSony(val, bits);
verify(val, bits, SONY);
}
void testRC5(unsigned long val, int bits) {
irsenddummy.reset();
irsenddummy.sendRC5(val, bits);
verify(val, bits, RC5);
}
void testRC6(unsigned long val, int bits) {
irsenddummy.reset();
irsenddummy.sendRC6(val, bits);
verify(val, bits, RC6);
}
void test() {
Serial.println("NEC tests");
testNEC(0x00000000, 32);
testNEC(0xffffffff, 32);
testNEC(0xaaaaaaaa, 32);
testNEC(0x55555555, 32);
testNEC(0x12345678, 32);
Serial.println("Sony tests");
testSony(0xfff, 12);
testSony(0x000, 12);
testSony(0xaaa, 12);
testSony(0x555, 12);
testSony(0x123, 12);
Serial.println("RC5 tests");
testRC5(0xfff, 12);
testRC5(0x000, 12);
testRC5(0xaaa, 12);
testRC5(0x555, 12);
testRC5(0x123, 12);
Serial.println("RC6 tests");
testRC6(0xfffff, 20);
testRC6(0x00000, 20);
testRC6(0xaaaaa, 20);
testRC6(0x55555, 20);
testRC6(0x12345, 20);
}
void setup()
{
Serial.begin(9600);
test();
}
void loop() {
}
/*
* IRremote: IRtest unittest
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
*
* 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
* the arduino IDE.
*/
#include <IRremote.h>
#include <IRremoteInt.h>
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
// decode_results *results = (decode_results *)v
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("");
}
IRrecv irrecv(0);
decode_results results;
class IRsendDummy :
public IRsend
{
public:
// For testing, just log the marks/spaces
#define SENDLOG_LEN 128
int sendlog[SENDLOG_LEN];
int sendlogcnt;
IRsendDummy() :
IRsend() {
}
void reset() {
sendlogcnt = 0;
}
void mark(int time) {
sendlog[sendlogcnt] = time;
if (sendlogcnt < SENDLOG_LEN) sendlogcnt++;
}
void space(int time) {
sendlog[sendlogcnt] = -time;
if (sendlogcnt < SENDLOG_LEN) sendlogcnt++;
}
// Copies the dummy buf into the interrupt buf
void useDummyBuf() {
int last = SPACE;
irparams.rcvstate = STATE_STOP;
irparams.rawlen = 1; // Skip the gap
for (int i = 0 ; i < sendlogcnt; i++) {
if (sendlog[i] < 0) {
if (last == MARK) {
// New space
irparams.rawbuf[irparams.rawlen++] = (-sendlog[i] - MARK_EXCESS) / USECPERTICK;
last = SPACE;
}
else {
// More space
irparams.rawbuf[irparams.rawlen - 1] += -sendlog[i] / USECPERTICK;
}
}
else if (sendlog[i] > 0) {
if (last == SPACE) {
// New mark
irparams.rawbuf[irparams.rawlen++] = (sendlog[i] + MARK_EXCESS) / USECPERTICK;
last = MARK;
}
else {
// More mark
irparams.rawbuf[irparams.rawlen - 1] += sendlog[i] / USECPERTICK;
}
}
}
if (irparams.rawlen % 2) {
irparams.rawlen--; // Remove trailing space
}
}
};
IRsendDummy irsenddummy;
void verify(unsigned long val, int bits, int type) {
irsenddummy.useDummyBuf();
irrecv.decode(&results);
Serial.print("Testing ");
Serial.print(val, HEX);
if (results.value == val && results.bits == bits && results.decode_type == type) {
Serial.println(": OK");
}
else {
Serial.println(": Error");
dump(&results);
}
}
void testNEC(unsigned long val, int bits) {
irsenddummy.reset();
irsenddummy.sendNEC(val, bits);
verify(val, bits, NEC);
}
void testSony(unsigned long val, int bits) {
irsenddummy.reset();
irsenddummy.sendSony(val, bits);
verify(val, bits, SONY);
}
void testRC5(unsigned long val, int bits) {
irsenddummy.reset();
irsenddummy.sendRC5(val, bits);
verify(val, bits, RC5);
}
void testRC6(unsigned long val, int bits) {
irsenddummy.reset();
irsenddummy.sendRC6(val, bits);
verify(val, bits, RC6);
}
void test() {
Serial.println("NEC tests");
testNEC(0x00000000, 32);
testNEC(0xffffffff, 32);
testNEC(0xaaaaaaaa, 32);
testNEC(0x55555555, 32);
testNEC(0x12345678, 32);
Serial.println("Sony tests");
testSony(0xfff, 12);
testSony(0x000, 12);
testSony(0xaaa, 12);
testSony(0x555, 12);
testSony(0x123, 12);
Serial.println("RC5 tests");
testRC5(0xfff, 12);
testRC5(0x000, 12);
testRC5(0xaaa, 12);
testRC5(0x555, 12);
testRC5(0x123, 12);
Serial.println("RC6 tests");
testRC6(0xfffff, 20);
testRC6(0x00000, 20);
testRC6(0xaaaaa, 20);
testRC6(0x55555, 20);
testRC6(0x12345, 20);
}
void setup()
{
Serial.begin(9600);
test();
}
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)
#######################################
decode_results KEYWORD1
IRrecv KEYWORD1
IRsend KEYWORD1
decode_results KEYWORD1
IRrecv KEYWORD1
IRsend KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
blink13 KEYWORD2
decode KEYWORD2
enableIRIn KEYWORD2
resume KEYWORD2
enableIROut KEYWORD2
sendNEC KEYWORD2
sendSony KEYWORD2
sendRaw KEYWORD2
sendRC5 KEYWORD2
sendRC6 KEYWORD2
blink13 KEYWORD2
decode KEYWORD2
enableIRIn KEYWORD2
resume KEYWORD2
enableIROut KEYWORD2
sendNEC KEYWORD2
sendSony KEYWORD2
sendSanyo KEYWORD2
sendMitsubishi KEYWORD2
sendRaw KEYWORD2
sendRC5 KEYWORD2
sendRC6 KEYWORD2
sendDISH KEYWORD2
sendSharp KEYWORD2
sendSharpRaw KEYWORD2
sendPanasonic KEYWORD2
sendJVC KEYWORD2
#
#######################################
# Constants (LITERAL1)
#######################################
NEC LITERAL1
SONY LITERAL1
RC5 LITERAL1
RC6 LITERAL1
UNKNOWN LITERAL1
REPEAT LITERAL1
NEC LITERAL1
SONY LITERAL1
SANYO LITERAL1
MITSUBISHI LITERAL1
RC5 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