diff --git a/IRremote.cpp b/IRremote.cpp index 8395c3a..ad17c46 100644 --- a/IRremote.cpp +++ b/IRremote.cpp @@ -9,6 +9,8 @@ * 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) */ #include "IRremote.h" @@ -167,7 +169,55 @@ void IRsend::sendRC6(unsigned long data, int nbits) } space(0); // Turn off at end } - +void IRsend::sendPanasonic(unsigned int address, unsigned long data) { + enableIROut(38); + 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::mark(int time) { // Sends an IR mark for the specified number of microseconds. // The mark output is modulated at the PWM frequency. @@ -362,6 +412,18 @@ int IRrecv::decode(decode_results *results) { if (decodeRC6(results)) { return DECODED; } +#ifdef DEBUG + Serial.println("Attempting Panasonic decode"); +#endif + if (decodePanasonic(results)) { + return DECODED; + } +#ifdef DEBUG + Serial.println("Attempting JVC decode"); +#endif + if (decodeJVC(results)) { + return DECODED; + } // decodeHash returns a hash on any input. // Thus, it needs to be last in the list. // If you add any decodes, add them before this. @@ -592,6 +654,90 @@ long IRrecv::decodeRC6(decode_results *results) { results->decode_type = RC6; 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::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; +} /* ----------------------------------------------------------------------- * hashdecode - decode an arbitrary IR code. diff --git a/IRremote.h b/IRremote.h index ef98ceb..acc2385 100644 --- a/IRremote.h +++ b/IRremote.h @@ -7,6 +7,8 @@ * 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) */ #ifndef IRremote_h @@ -24,6 +26,7 @@ class decode_results { public: int decode_type; // NEC, SONY, RC5, UNKNOWN + unsigned int panasonicAddress; // This is only used for decoding Panasonic data unsigned long value; // Decoded value int bits; // Number of bits in decoded value volatile unsigned int *rawbuf; // Raw intervals in .5 us ticks @@ -37,6 +40,8 @@ public: #define RC6 4 #define DISH 5 #define SHARP 6 +#define PANASONIC 7 +#define JVC 8 #define UNKNOWN -1 // Decoded value for NEC when a repeat code is received @@ -58,6 +63,8 @@ private: long decodeSony(decode_results *results); long decodeRC5(decode_results *results); long decodeRC6(decode_results *results); + long decodePanasonic(decode_results *results); + long decodeJVC(decode_results *results); long decodeHash(decode_results *results); int compare(unsigned int oldval, unsigned int newval); @@ -82,6 +89,8 @@ public: void sendRC6(unsigned long data, int nbits); void sendDISH(unsigned long data, int nbits); void sendSharp(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: void enableIROut(int khz); VIRTUAL void mark(int usec); @@ -92,7 +101,7 @@ public: // Some useful constants #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 // when received due to sensor lag. diff --git a/IRremoteInt.h b/IRremoteInt.h index 751a888..7dd7e63 100644 --- a/IRremoteInt.h +++ b/IRremoteInt.h @@ -9,12 +9,18 @@ * 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) */ #ifndef IRremoteint_h #define IRremoteint_h -#include +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif // define which timer to use // @@ -115,6 +121,19 @@ #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 SHARP_BITS 15 #define DISH_BITS 16 @@ -129,9 +148,9 @@ #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) +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 @@ -165,6 +184,8 @@ extern volatile irparams_t irparams; #define SONY_BITS 12 #define MIN_RC5_SAMPLES 11 #define MIN_RC6_SAMPLES 1 +#define PANASONIC_BITS 48 +#define JVC_BITS 16 diff --git a/examples/IRrecord/IRrecord.pde b/examples/IRrecord/IRrecord.ino similarity index 100% rename from examples/IRrecord/IRrecord.pde rename to examples/IRrecord/IRrecord.ino diff --git a/examples/IRrecvDemo/IRrecvDemo.pde b/examples/IRrecvDemo/IRrecvDemo.ino similarity index 100% rename from examples/IRrecvDemo/IRrecvDemo.pde rename to examples/IRrecvDemo/IRrecvDemo.ino diff --git a/examples/IRrecvDump/IRrecvDump.pde b/examples/IRrecvDump/IRrecvDump.ino similarity index 81% rename from examples/IRrecvDump/IRrecvDump.pde rename to examples/IRrecvDump/IRrecvDump.ino index 7fd52d0..6afcb0f 100644 --- a/examples/IRrecvDump/IRrecvDump.pde +++ b/examples/IRrecvDump/IRrecvDump.ino @@ -4,6 +4,7 @@ * 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 @@ -42,6 +43,14 @@ 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 == JVC) { + Serial.print("Decoded JVC: "); + } Serial.print(results->value, HEX); Serial.print(" ("); Serial.print(results->bits, DEC); diff --git a/examples/IRrelay/IRrelay.pde b/examples/IRrelay/IRrelay.ino similarity index 100% rename from examples/IRrelay/IRrelay.pde rename to examples/IRrelay/IRrelay.ino diff --git a/examples/IRsendDemo/IRsendDemo.pde b/examples/IRsendDemo/IRsendDemo.ino similarity index 100% rename from examples/IRsendDemo/IRsendDemo.pde rename to examples/IRsendDemo/IRsendDemo.ino diff --git a/examples/IRtest/IRtest.pde b/examples/IRtest/IRtest.ino similarity index 100% rename from examples/IRtest/IRtest.pde rename to examples/IRtest/IRtest.ino diff --git a/examples/IRtest2/IRtest2.pde b/examples/IRtest2/IRtest2.ino similarity index 100% rename from examples/IRtest2/IRtest2.pde rename to examples/IRtest2/IRtest2.ino diff --git a/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino new file mode 100644 index 0000000..33c167c --- /dev/null +++ b/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino @@ -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 + +#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); +}