61 Commits

Author SHA1 Message Date
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
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
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
9235051c6a Readme is branch independent 2015-03-07 23:33:59 -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
16 changed files with 2510 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.

View File

@@ -4,9 +4,18 @@
* 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
* *
* Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
* Modified by Mitra Ardron <mitra@mitra.biz>
* Added Sanyo and Mitsubishi controllers
* Modified Sony to spot the repeat codes that some Sony's send
*
* Interrupt code based on NECIRrcv by Joe Knapp * Interrupt code based on NECIRrcv by Joe Knapp
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 * 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/ * 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
*/ */
#include "IRremote.h" #include "IRremote.h"
@@ -58,6 +67,11 @@ int MATCH_SPACE(int measured_ticks, int desired_us) {
Serial.println(TICKS_HIGH(desired_us - MARK_EXCESS), DEC); Serial.println(TICKS_HIGH(desired_us - MARK_EXCESS), DEC);
return measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS); return measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS);
} }
#else
int MATCH(int measured, int desired) {return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);}
int MATCH_MARK(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us + MARK_EXCESS));}
int MATCH_SPACE(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us - MARK_EXCESS));}
// Debugging versions are in IRremote.cpp
#endif #endif
void IRsend::sendNEC(unsigned long data, int nbits) void IRsend::sendNEC(unsigned long data, int nbits)
@@ -80,6 +94,27 @@ void IRsend::sendNEC(unsigned long data, int nbits)
space(0); space(0);
} }
void IRsend::sendWhynter(unsigned long data, int nbits) {
enableIROut(38);
mark(WHYNTER_ZERO_MARK);
space(WHYNTER_ZERO_SPACE);
mark(WHYNTER_HDR_MARK);
space(WHYNTER_HDR_SPACE);
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
mark(WHYNTER_ONE_MARK);
space(WHYNTER_ONE_SPACE);
}
else {
mark(WHYNTER_ZERO_MARK);
space(WHYNTER_ZERO_SPACE);
}
data <<= 1;
}
mark(WHYNTER_ZERO_MARK);
space(WHYNTER_ZERO_SPACE);
}
void IRsend::sendSony(unsigned long data, int nbits) { void IRsend::sendSony(unsigned long data, int nbits) {
enableIROut(40); enableIROut(40);
mark(SONY_HDR_MARK); mark(SONY_HDR_MARK);
@@ -165,20 +200,89 @@ void IRsend::sendRC6(unsigned long data, int nbits)
} }
space(0); // Turn off at end space(0); // Turn off at end
} }
void IRsend::sendPanasonic(unsigned int address, unsigned long data) {
enableIROut(35);
mark(PANASONIC_HDR_MARK);
space(PANASONIC_HDR_SPACE);
for(int i=0;i<16;i++)
{
mark(PANASONIC_BIT_MARK);
if (address & 0x8000) {
space(PANASONIC_ONE_SPACE);
} else {
space(PANASONIC_ZERO_SPACE);
}
address <<= 1;
}
for (int i=0; i < 32; i++) {
mark(PANASONIC_BIT_MARK);
if (data & TOPBIT) {
space(PANASONIC_ONE_SPACE);
} else {
space(PANASONIC_ZERO_SPACE);
}
data <<= 1;
}
mark(PANASONIC_BIT_MARK);
space(0);
}
void IRsend::sendJVC(unsigned long data, int nbits, int repeat)
{
enableIROut(38);
data = data << (32 - nbits);
if (!repeat){
mark(JVC_HDR_MARK);
space(JVC_HDR_SPACE);
}
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
mark(JVC_BIT_MARK);
space(JVC_ONE_SPACE);
}
else {
mark(JVC_BIT_MARK);
space(JVC_ZERO_SPACE);
}
data <<= 1;
}
mark(JVC_BIT_MARK);
space(0);
}
void IRsend::sendSAMSUNG(unsigned long data, int nbits)
{
enableIROut(38);
mark(SAMSUNG_HDR_MARK);
space(SAMSUNG_HDR_SPACE);
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
mark(SAMSUNG_BIT_MARK);
space(SAMSUNG_ONE_SPACE);
}
else {
mark(SAMSUNG_BIT_MARK);
space(SAMSUNG_ZERO_SPACE);
}
data <<= 1;
}
mark(SAMSUNG_BIT_MARK);
space(0);
}
void IRsend::mark(int time) { void IRsend::mark(int time) {
// Sends an IR mark for the specified number of microseconds. // Sends an IR mark for the specified number of microseconds.
// The mark output is modulated at the PWM frequency. // The mark output is modulated at the PWM frequency.
TCCR2A |= _BV(COM2B1); // Enable pin 3 PWM output TIMER_ENABLE_PWM; // Enable pin 3 PWM output
delayMicroseconds(time); if (time > 0) delayMicroseconds(time);
} }
/* Leave pin off for time (given in microseconds) */ /* Leave pin off for time (given in microseconds) */
void IRsend::space(int time) { void IRsend::space(int time) {
// Sends an IR space for the specified number of microseconds. // Sends an IR space for the specified number of microseconds.
// A space is no output, so the PWM output is disabled. // A space is no output, so the PWM output is disabled.
TCCR2A &= ~(_BV(COM2B1)); // Disable pin 3 PWM output TIMER_DISABLE_PWM; // Disable pin 3 PWM output
delayMicroseconds(time); if (time > 0) delayMicroseconds(time);
} }
void IRsend::enableIROut(int khz) { void IRsend::enableIROut(int khz) {
@@ -195,21 +299,17 @@ void IRsend::enableIROut(int khz) {
// Disable the Timer2 Interrupt (which is used for receiving IR) // Disable the Timer2 Interrupt (which is used for receiving IR)
TIMSK2 &= ~_BV(TOIE2); //Timer2 Overflow Interrupt TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt
pinMode(3, OUTPUT); pinMode(TIMER_PWM_PIN, OUTPUT);
digitalWrite(3, LOW); // When not sending PWM, we want it low digitalWrite(TIMER_PWM_PIN, LOW); // When not sending PWM, we want it low
// COM2A = 00: disconnect OC2A // COM2A = 00: disconnect OC2A
// COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted // COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted
// WGM2 = 101: phase-correct PWM with OCRA as top // WGM2 = 101: phase-correct PWM with OCRA as top
// CS2 = 000: no prescaling // CS2 = 000: no prescaling
TCCR2A = _BV(WGM20);
TCCR2B = _BV(WGM22) | _BV(CS20);
// The top value for the timer. The modulation frequency will be SYSCLOCK / 2 / OCR2A. // The top value for the timer. The modulation frequency will be SYSCLOCK / 2 / OCR2A.
OCR2A = SYSCLOCK / 2 / khz / 1000; TIMER_CONFIG_KHZ(khz);
OCR2B = OCR2A / 3; // 33% duty cycle
} }
IRrecv::IRrecv(int recvpin) IRrecv::IRrecv(int recvpin)
@@ -220,20 +320,17 @@ IRrecv::IRrecv(int recvpin)
// initialization // initialization
void IRrecv::enableIRIn() { void IRrecv::enableIRIn() {
cli();
// setup pulse clock timer interrupt // setup pulse clock timer interrupt
TCCR2A = 0; // normal mode
//Prescale /8 (16M/8 = 0.5 microseconds per tick) //Prescale /8 (16M/8 = 0.5 microseconds per tick)
// Therefore, the timer interval can range from 0.5 to 128 microseconds // Therefore, the timer interval can range from 0.5 to 128 microseconds
// depending on the reset value (255 to 0) // depending on the reset value (255 to 0)
cbi(TCCR2B,CS22); TIMER_CONFIG_NORMAL();
sbi(TCCR2B,CS21);
cbi(TCCR2B,CS20);
//Timer2 Overflow Interrupt Enable //Timer2 Overflow Interrupt Enable
sbi(TIMSK2,TOIE2); TIMER_ENABLE_INTR;
RESET_TIMER2; TIMER_RESET;
sei(); // enable interrupts sei(); // enable interrupts
@@ -241,7 +338,6 @@ void IRrecv::enableIRIn() {
irparams.rcvstate = STATE_IDLE; irparams.rcvstate = STATE_IDLE;
irparams.rawlen = 0; irparams.rawlen = 0;
// set pin modes // set pin modes
pinMode(irparams.recvpin, INPUT); pinMode(irparams.recvpin, INPUT);
} }
@@ -261,9 +357,9 @@ void IRrecv::blink13(int blinkflag)
// First entry is the SPACE between transmissions. // First entry is the SPACE between transmissions.
// As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues. // As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues.
// As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts // As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts
ISR(TIMER2_OVF_vect) ISR(TIMER_INTR_NAME)
{ {
RESET_TIMER2; TIMER_RESET;
uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin); uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin);
@@ -320,10 +416,10 @@ ISR(TIMER2_OVF_vect)
if (irparams.blinkflag) { if (irparams.blinkflag) {
if (irdata == MARK) { if (irdata == MARK) {
PORTB |= B00100000; // turn pin 13 LED on BLINKLED_ON(); // turn pin 13 LED on
} }
else { else {
PORTB &= B11011111; // turn pin 13 LED off BLINKLED_OFF(); // turn pin 13 LED off
} }
} }
} }
@@ -356,6 +452,18 @@ int IRrecv::decode(decode_results *results) {
if (decodeSony(results)) { if (decodeSony(results)) {
return DECODED; return DECODED;
} }
#ifdef DEBUG
Serial.println("Attempting Sanyo decode");
#endif
if (decodeSanyo(results)) {
return DECODED;
}
#ifdef DEBUG
Serial.println("Attempting Mitsubishi decode");
#endif
if (decodeMitsubishi(results)) {
return DECODED;
}
#ifdef DEBUG #ifdef DEBUG
Serial.println("Attempting RC5 decode"); Serial.println("Attempting RC5 decode");
#endif #endif
@@ -368,6 +476,36 @@ int IRrecv::decode(decode_results *results) {
if (decodeRC6(results)) { if (decodeRC6(results)) {
return DECODED; return DECODED;
} }
#ifdef DEBUG
Serial.println("Attempting Panasonic decode");
#endif
if (decodePanasonic(results)) {
return DECODED;
}
#ifdef DEBUG
Serial.println("Attempting LG decode");
#endif
if (decodeLG(results)) {
return DECODED;
}
#ifdef DEBUG
Serial.println("Attempting JVC decode");
#endif
if (decodeJVC(results)) {
return DECODED;
}
#ifdef DEBUG
Serial.println("Attempting SAMSUNG decode");
#endif
if (decodeSAMSUNG(results)) {
return DECODED;
}
#ifdef DEBUG
Serial.println("Attempting Whynter decode");
#endif
if (decodeWhynter(results)) {
return DECODED;
}
// decodeHash returns a hash on any input. // decodeHash returns a hash on any input.
// Thus, it needs to be last in the list. // Thus, it needs to be last in the list.
// If you add any decodes, add them before this. // If you add any decodes, add them before this.
@@ -379,6 +517,7 @@ int IRrecv::decode(decode_results *results) {
return ERR; return ERR;
} }
// NECs have a repeat only 4 items long
long IRrecv::decodeNEC(decode_results *results) { long IRrecv::decodeNEC(decode_results *results) {
long data = 0; long data = 0;
int offset = 1; // Skip first space int offset = 1; // Skip first space
@@ -432,7 +571,19 @@ long IRrecv::decodeSony(decode_results *results) {
if (irparams.rawlen < 2 * SONY_BITS + 2) { if (irparams.rawlen < 2 * SONY_BITS + 2) {
return ERR; return ERR;
} }
int offset = 1; // Skip first space int offset = 0; // Dont skip first space, check its size
// Some Sony's deliver repeats fast after first
// unfortunately can't spot difference from of repeat from two fast clicks
if (results->rawbuf[offset] < SONY_DOUBLE_SPACE_USECS) {
// Serial.print("IR Gap found: ");
results->bits = 0;
results->value = REPEAT;
results->decode_type = SANYO;
return DECODED;
}
offset++;
// Initial mark // Initial mark
if (!MATCH_MARK(results->rawbuf[offset], SONY_HDR_MARK)) { if (!MATCH_MARK(results->rawbuf[offset], SONY_HDR_MARK)) {
return ERR; return ERR;
@@ -467,6 +618,194 @@ long IRrecv::decodeSony(decode_results *results) {
return DECODED; return DECODED;
} }
long IRrecv::decodeWhynter(decode_results *results) {
long data = 0;
if (irparams.rawlen < 2 * WHYNTER_BITS + 6) {
return ERR;
}
int offset = 1; // skip initial space
// sequence begins with a bit mark and a zero space
if (!MATCH_MARK(results->rawbuf[offset], WHYNTER_BIT_MARK)) {
return ERR;
}
offset++;
if (!MATCH_SPACE(results->rawbuf[offset], WHYNTER_ZERO_SPACE)) {
return ERR;
}
offset++;
// header mark and space
if (!MATCH_MARK(results->rawbuf[offset], WHYNTER_HDR_MARK)) {
return ERR;
}
offset++;
if (!MATCH_SPACE(results->rawbuf[offset], WHYNTER_HDR_SPACE)) {
return ERR;
}
offset++;
// data bits
for (int i = 0; i < WHYNTER_BITS; i++) {
if (!MATCH_MARK(results->rawbuf[offset], WHYNTER_BIT_MARK)) {
return ERR;
}
offset++;
if (MATCH_SPACE(results->rawbuf[offset], WHYNTER_ONE_SPACE)) {
data = (data << 1) | 1;
}
else if (MATCH_SPACE(results->rawbuf[offset],WHYNTER_ZERO_SPACE)) {
data <<= 1;
}
else {
return ERR;
}
offset++;
}
// trailing mark
if (!MATCH_MARK(results->rawbuf[offset], WHYNTER_BIT_MARK)) {
return ERR;
}
// Success
results->bits = WHYNTER_BITS;
results->value = data;
results->decode_type = WHYNTER;
return DECODED;
}
// I think this is a Sanyo decoder - serial = SA 8650B
// Looks like Sony except for timings, 48 chars of data and time/space different
long IRrecv::decodeSanyo(decode_results *results) {
long data = 0;
if (irparams.rawlen < 2 * SANYO_BITS + 2) {
return ERR;
}
int offset = 0; // Skip first space
// Initial space
/* Put this back in for debugging - note can't use #DEBUG as if Debug on we don't see the repeat cos of the delay
Serial.print("IR Gap: ");
Serial.println( results->rawbuf[offset]);
Serial.println( "test against:");
Serial.println(results->rawbuf[offset]);
*/
if (results->rawbuf[offset] < SANYO_DOUBLE_SPACE_USECS) {
// Serial.print("IR Gap found: ");
results->bits = 0;
results->value = REPEAT;
results->decode_type = SANYO;
return DECODED;
}
offset++;
// Initial mark
if (!MATCH_MARK(results->rawbuf[offset], SANYO_HDR_MARK)) {
return ERR;
}
offset++;
// Skip Second Mark
if (!MATCH_MARK(results->rawbuf[offset], SANYO_HDR_MARK)) {
return ERR;
}
offset++;
while (offset + 1 < irparams.rawlen) {
if (!MATCH_SPACE(results->rawbuf[offset], SANYO_HDR_SPACE)) {
break;
}
offset++;
if (MATCH_MARK(results->rawbuf[offset], SANYO_ONE_MARK)) {
data = (data << 1) | 1;
}
else if (MATCH_MARK(results->rawbuf[offset], SANYO_ZERO_MARK)) {
data <<= 1;
}
else {
return ERR;
}
offset++;
}
// Success
results->bits = (offset - 1) / 2;
if (results->bits < 12) {
results->bits = 0;
return ERR;
}
results->value = data;
results->decode_type = SANYO;
return DECODED;
}
// Looks like Sony except for timings, 48 chars of data and time/space different
long IRrecv::decodeMitsubishi(decode_results *results) {
// Serial.print("?!? decoding Mitsubishi:");Serial.print(irparams.rawlen); Serial.print(" want "); Serial.println( 2 * MITSUBISHI_BITS + 2);
long data = 0;
if (irparams.rawlen < 2 * MITSUBISHI_BITS + 2) {
return ERR;
}
int offset = 0; // Skip first space
// Initial space
/* Put this back in for debugging - note can't use #DEBUG as if Debug on we don't see the repeat cos of the delay
Serial.print("IR Gap: ");
Serial.println( results->rawbuf[offset]);
Serial.println( "test against:");
Serial.println(results->rawbuf[offset]);
*/
/* Not seeing double keys from Mitsubishi
if (results->rawbuf[offset] < MITSUBISHI_DOUBLE_SPACE_USECS) {
// Serial.print("IR Gap found: ");
results->bits = 0;
results->value = REPEAT;
results->decode_type = MITSUBISHI;
return DECODED;
}
*/
offset++;
// Typical
// 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
// Initial Space
if (!MATCH_MARK(results->rawbuf[offset], MITSUBISHI_HDR_SPACE)) {
return ERR;
}
offset++;
while (offset + 1 < irparams.rawlen) {
if (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ONE_MARK)) {
data = (data << 1) | 1;
}
else if (MATCH_MARK(results->rawbuf[offset], MITSUBISHI_ZERO_MARK)) {
data <<= 1;
}
else {
// Serial.println("A"); Serial.println(offset); Serial.println(results->rawbuf[offset]);
return ERR;
}
offset++;
if (!MATCH_SPACE(results->rawbuf[offset], MITSUBISHI_HDR_SPACE)) {
// Serial.println("B"); Serial.println(offset); Serial.println(results->rawbuf[offset]);
break;
}
offset++;
}
// Success
results->bits = (offset - 1) / 2;
if (results->bits < MITSUBISHI_BITS) {
results->bits = 0;
return ERR;
}
results->value = data;
results->decode_type = MITSUBISHI;
return DECODED;
}
// Gets one undecoded level at a time from the raw buffer. // Gets one undecoded level at a time from the raw buffer.
// The RC5/6 decoding is easier if the data is broken into time intervals. // The RC5/6 decoding is easier if the data is broken into time intervals.
// E.g. if the buffer has MARK for 2 time intervals and SPACE for 1, // E.g. if the buffer has MARK for 2 time intervals and SPACE for 1,
@@ -598,6 +937,185 @@ long IRrecv::decodeRC6(decode_results *results) {
results->decode_type = RC6; results->decode_type = RC6;
return DECODED; return DECODED;
} }
long IRrecv::decodePanasonic(decode_results *results) {
unsigned long long data = 0;
int offset = 1;
if (!MATCH_MARK(results->rawbuf[offset], PANASONIC_HDR_MARK)) {
return ERR;
}
offset++;
if (!MATCH_MARK(results->rawbuf[offset], PANASONIC_HDR_SPACE)) {
return ERR;
}
offset++;
// decode address
for (int i = 0; i < PANASONIC_BITS; i++) {
if (!MATCH_MARK(results->rawbuf[offset++], PANASONIC_BIT_MARK)) {
return ERR;
}
if (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ONE_SPACE)) {
data = (data << 1) | 1;
} else if (MATCH_SPACE(results->rawbuf[offset],PANASONIC_ZERO_SPACE)) {
data <<= 1;
} else {
return ERR;
}
offset++;
}
results->value = (unsigned long)data;
results->panasonicAddress = (unsigned int)(data >> 32);
results->decode_type = PANASONIC;
results->bits = PANASONIC_BITS;
return DECODED;
}
long IRrecv::decodeLG(decode_results *results) {
long data = 0;
int offset = 1; // Skip first space
// Initial mark
if (!MATCH_MARK(results->rawbuf[offset], LG_HDR_MARK)) {
return ERR;
}
offset++;
if (irparams.rawlen < 2 * LG_BITS + 1 ) {
return ERR;
}
// Initial space
if (!MATCH_SPACE(results->rawbuf[offset], LG_HDR_SPACE)) {
return ERR;
}
offset++;
for (int i = 0; i < LG_BITS; i++) {
if (!MATCH_MARK(results->rawbuf[offset], LG_BIT_MARK)) {
return ERR;
}
offset++;
if (MATCH_SPACE(results->rawbuf[offset], LG_ONE_SPACE)) {
data = (data << 1) | 1;
}
else if (MATCH_SPACE(results->rawbuf[offset], LG_ZERO_SPACE)) {
data <<= 1;
}
else {
return ERR;
}
offset++;
}
//Stop bit
if (!MATCH_MARK(results->rawbuf[offset], LG_BIT_MARK)){
return ERR;
}
// Success
results->bits = LG_BITS;
results->value = data;
results->decode_type = LG;
return DECODED;
}
long IRrecv::decodeJVC(decode_results *results) {
long data = 0;
int offset = 1; // Skip first space
// Check for repeat
if (irparams.rawlen - 1 == 33 &&
MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK) &&
MATCH_MARK(results->rawbuf[irparams.rawlen-1], JVC_BIT_MARK)) {
results->bits = 0;
results->value = REPEAT;
results->decode_type = JVC;
return DECODED;
}
// Initial mark
if (!MATCH_MARK(results->rawbuf[offset], JVC_HDR_MARK)) {
return ERR;
}
offset++;
if (irparams.rawlen < 2 * JVC_BITS + 1 ) {
return ERR;
}
// Initial space
if (!MATCH_SPACE(results->rawbuf[offset], JVC_HDR_SPACE)) {
return ERR;
}
offset++;
for (int i = 0; i < JVC_BITS; i++) {
if (!MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK)) {
return ERR;
}
offset++;
if (MATCH_SPACE(results->rawbuf[offset], JVC_ONE_SPACE)) {
data = (data << 1) | 1;
}
else if (MATCH_SPACE(results->rawbuf[offset], JVC_ZERO_SPACE)) {
data <<= 1;
}
else {
return ERR;
}
offset++;
}
//Stop bit
if (!MATCH_MARK(results->rawbuf[offset], JVC_BIT_MARK)){
return ERR;
}
// Success
results->bits = JVC_BITS;
results->value = data;
results->decode_type = JVC;
return DECODED;
}
// SAMSUNGs have a repeat only 4 items long
long IRrecv::decodeSAMSUNG(decode_results *results) {
long data = 0;
int offset = 1; // Skip first space
// Initial mark
if (!MATCH_MARK(results->rawbuf[offset], SAMSUNG_HDR_MARK)) {
return ERR;
}
offset++;
// Check for repeat
if (irparams.rawlen == 4 &&
MATCH_SPACE(results->rawbuf[offset], SAMSUNG_RPT_SPACE) &&
MATCH_MARK(results->rawbuf[offset+1], SAMSUNG_BIT_MARK)) {
results->bits = 0;
results->value = REPEAT;
results->decode_type = SAMSUNG;
return DECODED;
}
if (irparams.rawlen < 2 * SAMSUNG_BITS + 4) {
return ERR;
}
// Initial space
if (!MATCH_SPACE(results->rawbuf[offset], SAMSUNG_HDR_SPACE)) {
return ERR;
}
offset++;
for (int i = 0; i < SAMSUNG_BITS; i++) {
if (!MATCH_MARK(results->rawbuf[offset], SAMSUNG_BIT_MARK)) {
return ERR;
}
offset++;
if (MATCH_SPACE(results->rawbuf[offset], SAMSUNG_ONE_SPACE)) {
data = (data << 1) | 1;
}
else if (MATCH_SPACE(results->rawbuf[offset], SAMSUNG_ZERO_SPACE)) {
data <<= 1;
}
else {
return ERR;
}
offset++;
}
// Success
results->bits = SAMSUNG_BITS;
results->value = data;
results->decode_type = SAMSUNG;
return DECODED;
}
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
* hashdecode - decode an arbitrary IR code. * hashdecode - decode an arbitrary IR code.
@@ -653,11 +1171,13 @@ long IRrecv::decodeHash(decode_results *results) {
return DECODED; return DECODED;
} }
/* Sharp and DISH support by Todd Treece /* Sharp and DISH support by Todd Treece ( http://unionbridge.org/design/ircommand )
The Dish send function needs to be repeated 4 times and the Sharp function The Dish send function needs to be repeated 4 times, and the Sharp function
has the necessary repeats built in. I know that it's not consistent, has the necessary repeat built in because of the need to invert the signal.
but I don't have the time to update my code.
Sharp protocol documentation:
http://www.sbprojects.com/knowledge/ir/sharp.htm
Here are the LIRC files that I found that seem to match the remote codes Here are the LIRC files that I found that seem to match the remote codes
from the oscilloscope: from the oscilloscope:
@@ -673,42 +1193,37 @@ i.e. use 0x1C10 instead of 0x0000000000001C10 which is listed in the
linked LIRC file. linked LIRC file.
*/ */
void IRsend::sendSharp(unsigned long data, int nbits) { void IRsend::sendSharpRaw(unsigned long data, int nbits) {
unsigned long invertdata = data ^ SHARP_TOGGLE_MASK;
enableIROut(38); enableIROut(38);
for (int i = 0; i < nbits; i++) {
if (data & 0x4000) {
mark(SHARP_BIT_MARK);
space(SHARP_ONE_SPACE);
}
else {
mark(SHARP_BIT_MARK);
space(SHARP_ZERO_SPACE);
}
data <<= 1;
}
mark(SHARP_BIT_MARK); // Sending codes in bursts of 3 (normal, inverted, normal) makes transmission
space(SHARP_ZERO_SPACE); // much more reliable. That's the exact behaviour of CD-S6470 remote control.
delay(46); for (int n = 0; n < 3; n++) {
for (int i = 0; i < nbits; i++) { for (int i = 1 << (nbits-1); i > 0; i>>=1) {
if (invertdata & 0x4000) { if (data & i) {
mark(SHARP_BIT_MARK); mark(SHARP_BIT_MARK);
space(SHARP_ONE_SPACE); space(SHARP_ONE_SPACE);
}
else {
mark(SHARP_BIT_MARK);
space(SHARP_ZERO_SPACE);
}
} }
else {
mark(SHARP_BIT_MARK); mark(SHARP_BIT_MARK);
space(SHARP_ZERO_SPACE); space(SHARP_ZERO_SPACE);
} delay(40);
invertdata <<= 1;
data = data ^ SHARP_TOGGLE_MASK;
} }
mark(SHARP_BIT_MARK);
space(SHARP_ZERO_SPACE);
delay(46);
} }
void IRsend::sendDISH(unsigned long data, int nbits) // Sharp send compatible with data obtained through decodeSharp
{ void IRsend::sendSharp(unsigned int address, unsigned int command) {
sendSharpRaw((address << 10) | (command << 2) | 2, 15);
}
void IRsend::sendDISH(unsigned long data, int nbits) {
enableIROut(56); enableIROut(56);
mark(DISH_HDR_MARK); mark(DISH_HDR_MARK);
space(DISH_HDR_SPACE); space(DISH_HDR_SPACE);

View File

@@ -3,10 +3,15 @@
* 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 * Interrupt code based on NECIRrcv by Joe Knapp
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 * 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/ * 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 #ifndef IRremote_h
@@ -17,13 +22,17 @@
// If DEBUG is defined, a lot of debugging output will be printed during decoding. // 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 // 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. // methods virtual, which will be slightly slower, which is why it is optional.
// #define DEBUG //#define DEBUG
// #define TEST // #define TEST
// Results returned from the decoder // Results returned from the decoder
class decode_results { class decode_results {
public: public:
int decode_type; // NEC, SONY, RC5, UNKNOWN int decode_type; // NEC, SONY, RC5, UNKNOWN
union { // This is used for decoding Panasonic and Sharp data
unsigned int panasonicAddress;
unsigned int sharpAddress;
};
unsigned long value; // Decoded value unsigned long value; // Decoded value
int bits; // Number of bits in decoded value int bits; // Number of bits in decoded value
volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks
@@ -37,6 +46,13 @@ public:
#define RC6 4 #define RC6 4
#define DISH 5 #define DISH 5
#define SHARP 6 #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 UNKNOWN -1 #define UNKNOWN -1
// Decoded value for NEC when a repeat code is received // Decoded value for NEC when a repeat code is received
@@ -56,13 +72,19 @@ private:
int getRClevel(decode_results *results, int *offset, int *used, int t1); int getRClevel(decode_results *results, int *offset, int *used, int t1);
long decodeNEC(decode_results *results); long decodeNEC(decode_results *results);
long decodeSony(decode_results *results); long decodeSony(decode_results *results);
long decodeSanyo(decode_results *results);
long decodeMitsubishi(decode_results *results);
long decodeRC5(decode_results *results); long decodeRC5(decode_results *results);
long decodeRC6(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 decodeHash(decode_results *results); long decodeHash(decode_results *results);
int compare(unsigned int oldval, unsigned int newval); int compare(unsigned int oldval, unsigned int newval);
} } ;
;
// Only used for testing; can remove virtual for shorter code // Only used for testing; can remove virtual for shorter code
#ifdef TEST #ifdef TEST
@@ -75,24 +97,31 @@ class IRsend
{ {
public: public:
IRsend() {} IRsend() {}
void sendWhynter(unsigned long data, int nbits);
void sendNEC(unsigned long data, int nbits); void sendNEC(unsigned long data, int nbits);
void sendSony(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 sendRaw(unsigned int buf[], int len, int hz);
void sendRC5(unsigned long data, int nbits); void sendRC5(unsigned long data, int nbits);
void sendRC6(unsigned long data, int nbits); void sendRC6(unsigned long data, int nbits);
void sendDISH(unsigned long data, int nbits); void sendDISH(unsigned long data, int nbits);
void sendSharp(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.
// private: // private:
void sendSAMSUNG(unsigned long data, int nbits);
void enableIROut(int khz); void enableIROut(int khz);
VIRTUAL void mark(int usec); VIRTUAL void mark(int usec);
VIRTUAL void space(int usec); VIRTUAL void space(int usec);
} } ;
;
// Some useful constants // Some useful constants
#define USECPERTICK 50 // microseconds per clock interrupt tick #define USECPERTICK 50 // microseconds per clock interrupt tick
#define RAWBUF 76 // Length of raw duration buffer #define RAWBUF 100 // Length of raw duration buffer
// Marks tend to be 100us too long, and spaces 100us too short // Marks tend to be 100us too long, and spaces 100us too short
// when received due to sensor lag. // when received due to sensor lag.

View File

@@ -4,26 +4,85 @@
* 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
* *
* Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
*
* Interrupt code based on NECIRrcv by Joe Knapp * Interrupt code based on NECIRrcv by Joe Knapp
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 * 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/ * 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 #ifndef IRremoteint_h
#define IRremoteint_h #define IRremoteint_h
#if defined(ARDUINO) && ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h> #include <WProgram.h>
#endif
#define CLKFUDGE 5 // fudge factor for clock interrupt overhead // define which timer to use
#define CLK 256 // max value for clock (timer 2) //
#define PRESCALE 8 // timer2 clock prescale // 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 #define SYSCLOCK 16000000 // main Arduino clock
#define CLKSPERUSEC (SYSCLOCK/PRESCALE/1000000) // timer clocks per microsecond #endif
#define ERR 0 #define ERR 0
#define DECODED 1 #define DECODED 1
#define BLINKLED 13
// defines for setting and clearing register bits // defines for setting and clearing register bits
#ifndef cbi #ifndef cbi
@@ -33,15 +92,21 @@
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif #endif
// clock timer reset value // Pulse parms are *50-100 for the Mark and *50+100 for the space
#define INIT_TIMER_COUNT2 (CLK - USECPERTICK*CLKSPERUSEC + CLKFUDGE) // First MARK is the one after the long gap
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT2
// pulse parameters in usec // 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_MARK 9000
#define NEC_HDR_SPACE 4500 #define NEC_HDR_SPACE 4500
#define NEC_BIT_MARK 560 #define NEC_BIT_MARK 560
#define NEC_ONE_SPACE 1600 #define NEC_ONE_SPACE 1690
#define NEC_ZERO_SPACE 560 #define NEC_ZERO_SPACE 560
#define NEC_RPT_SPACE 2250 #define NEC_RPT_SPACE 2250
@@ -50,6 +115,26 @@
#define SONY_ONE_MARK 1200 #define SONY_ONE_MARK 1200
#define SONY_ZERO_MARK 600 #define SONY_ZERO_MARK 600
#define SONY_RPT_LENGTH 45000 #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_T1 889
#define RC5_RPT_LENGTH 46000 #define RC5_RPT_LENGTH 46000
@@ -74,6 +159,34 @@
#define DISH_RPT_SPACE 6200 #define DISH_RPT_SPACE 6200
#define DISH_TOP_BIT 0x8000 #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 SHARP_BITS 15
#define DISH_BITS 16 #define DISH_BITS 16
@@ -87,13 +200,6 @@
#define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK)) #define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK))
#define TICKS_HIGH(us) (int) (((us)*UTOL/USECPERTICK + 1)) #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 // receiver states
#define STATE_IDLE 2 #define STATE_IDLE 2
#define STATE_MARK 3 #define STATE_MARK 3
@@ -122,8 +228,298 @@ extern volatile irparams_t irparams;
#define NEC_BITS 32 #define NEC_BITS 32
#define SONY_BITS 12 #define SONY_BITS 12
#define SANYO_BITS 12
#define MITSUBISHI_BITS 16
#define MIN_RC5_SAMPLES 11 #define MIN_RC5_SAMPLES 11
#define MIN_RC6_SAMPLES 1 #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 #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

23
README.md Normal file
View File

@@ -0,0 +1,23 @@
# IRremote Arduino Library
This library enables you to send and receive using infra-red signals on an arduino
## Version - 1.00
## Installation
1. Click "Download ZIP"
2. Extract the downloaded zip file
3. Rename the extracted folder from "Arduino-IRremote" to "IRremote"
4. Move this folder 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

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,20 @@ 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 == LG) {
Serial.print("Decoded LG: ");
}
else if (results->decode_type == JVC) {
Serial.print("Decoded JVC: ");
}
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);

View File

@@ -23,4 +23,3 @@ 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,47 @@
# 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
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