From 78e9b87a3425815552e73c29133ce5296196d1cd Mon Sep 17 00:00:00 2001 From: Bluechip Date: Sun, 21 Jun 2015 01:20:44 +0100 Subject: [PATCH] Add Denon support Improve comments Fixup DECODE_AIWA_RC_T50 Simplify template --- IRremote.h | 12 ++++ examples/IRrecvDumpV2/IRrecvDumpV2.ino | 1 + irRecv.cpp | 17 ++++- ir_Denon.cpp | 86 ++++++++++++++++++++++++++ ir_Template.cpp | 44 ++++++------- 5 files changed, 135 insertions(+), 25 deletions(-) create mode 100644 ir_Denon.cpp diff --git a/IRremote.h b/IRremote.h index 47a0e06..cb8d958 100644 --- a/IRremote.h +++ b/IRremote.h @@ -70,6 +70,9 @@ #define DECODE_SHARP 0 // NOT WRITTEN #define SEND_SHARP 1 +#define DECODE_DENON 1 +#define SEND_DENON 1 + //------------------------------------------------------------------------------ // An enumerated list of all supported formats // You do NOT need to remove entries from this list when disabling protocols! @@ -92,6 +95,7 @@ typedef MITSUBISHI, DISH, SHARP, + DENON, } decode_type_t; @@ -213,6 +217,10 @@ class IRrecv //...................................................................... # if DECODE_SHARP bool decodeSharp (decode_results *results) ; // NOT WRITTEN +# endif + //...................................................................... +# if DECODE_DENON + bool decodeDenon (decode_results *results) ; # endif } ; @@ -288,6 +296,10 @@ class IRsend # if SEND_SHARP void sendSharpRaw (unsigned long data, int nbits) ; void sendSharp (unsigned int address, unsigned int command) ; +# endif + //...................................................................... +# if SEND_DENON + void sendDenon (unsigned long data, int nbits) ; # endif } ; diff --git a/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/examples/IRrecvDumpV2/IRrecvDumpV2.ino index c9b7ff4..a610bff 100644 --- a/examples/IRrecvDumpV2/IRrecvDumpV2.ino +++ b/examples/IRrecvDumpV2/IRrecvDumpV2.ino @@ -54,6 +54,7 @@ void encoding (decode_results *results) case WHYNTER: Serial.print("WHYNTER"); break ; case AIWA_RC_T501: Serial.print("AIWA_RC_T501"); break ; case PANASONIC: Serial.print("PANASONIC"); break ; + case DENON: Serial.print("Denon"); break ; } } diff --git a/irRecv.cpp b/irRecv.cpp index 8bcb0bf..d3a7060 100644 --- a/irRecv.cpp +++ b/irRecv.cpp @@ -45,6 +45,8 @@ void IRrecv::blink13 (int blinkflag) } //+============================================================================= +// Restart the ISR state machine +// void IRrecv::resume ( ) { irparams.rcvstate = STATE_IDLE; @@ -55,6 +57,7 @@ void IRrecv::resume ( ) // Decodes the received IR message // Returns 0 if no data ready, 1 if data ready. // Results of decoding are stored in results +// int IRrecv::decode (decode_results *results) { results->rawbuf = irparams.rawbuf; @@ -119,15 +122,21 @@ int IRrecv::decode (decode_results *results) if (decodeWhynter(results)) return true ; #endif -#ifdef AIWA_RC_T501 +#ifdef DECODE_AIWA_RC_T501 DBG_PRINTLN("Attempting Aiwa RC-T501 decode"); if (decodeAiwaRCT501(results)) return true ; #endif +#ifdef DECODE_DENON + DBG_PRINTLN("Attempting Denon decode"); + if (decodeDenon(results)) return true ; +#endif + // 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. if (decodeHash(results)) return true ; + // Throw away and start over resume(); return false; @@ -140,7 +149,7 @@ int IRrecv::decode (decode_results *results) // // The algorithm: look at the sequence of MARK signals, and see if each one // is shorter (0), the same length (1), or longer (2) than the previous. -// Do the same with the SPACE signals. Hszh the resulting sequence of 0's, +// Do the same with the SPACE signals. Hash the resulting sequence of 0's, // 1's, and 2's to a 32-bit value. This will give a unique value for each // different code (probably), for most code systems. // @@ -168,9 +177,11 @@ int IRrecv::compare (unsigned int oldval, unsigned int newval) long IRrecv::decodeHash (decode_results *results) { + long hash = FNV_BASIS_32; + // Require at least 6 samples to prevent triggering on noise if (results->rawlen < 6) return false ; - long hash = FNV_BASIS_32; + for (int i = 1; (i + 2) < results->rawlen; i++) { int value = compare(results->rawbuf[i], results->rawbuf[i+2]); // Add value into the hash diff --git a/ir_Denon.cpp b/ir_Denon.cpp new file mode 100644 index 0000000..4ce6862 --- /dev/null +++ b/ir_Denon.cpp @@ -0,0 +1,86 @@ +#include "IRremote.h" +#include "IRremoteInt.h" + +// Reverse Engineerd by looking at RAW dumps generated by IRremote + +//============================================================================== +// DDDD EEEEE N N OOO N N +// D D E NN N O O NN N +// D D EEE N N N O O N N N +// D D E N NN O O N NN +// DDDD EEEEE N N OOO N N +//============================================================================== + +#define BITS 14 // The number of bits in the command + +#define HDR_MARK 300 // The length of the Header:Mark +#define HDR_SPACE 750 // The lenght of the Header:Space + +#define BIT_MARK 300 // The length of a Bit:Mark +#define ONE_SPACE 1800 // The length of a Bit:Space for 1's +#define ZERO_SPACE 750 // The length of a Bit:Space for 0's + +//+============================================================================= +// +#if SEND_DENON +void IRsend::sendDenon (unsigned long data, int nbits) +{ + // Set IR carrier frequency + enableIROut(38); + + // Header + mark (HDR_MARK); + space(HDR_SPACE); + + // Data + for (unsigned long mask = 1 << (nbits - 1); mask; mask >>= 1) { + if (data & mask) { + mark (BIT_MARK); + space(ONE_SPACE); + } else { + mark (BIT_MARK); + space(ZERO_SPACE); + } + } + + // Footer + mark(BIT_MARK); + space(0); // Always end with the LED off +} +#endif + +//+============================================================================= +// +#if DECODE_DENON +bool IRrecv::decodeDenon (decode_results *results) +{ + unsigned long data = 0; // Somewhere to build our code + int offset = 1; // Skip the Gap reading + + // Check we have the right amount of data + if (irparams.rawlen != 1 + 2 + (2 * BITS) + 1) return false ; + + // Check initial Mark+Space match + if (!MATCH_MARK (results->rawbuf[offset++], HDR_MARK )) return false ; + if (!MATCH_SPACE(results->rawbuf[offset++], HDR_SPACE)) return false ; + + // Read the bits in + for (int i = 0; i < BITS; i++) { + // Each bit looks like: MARK + SPACE_1 -> 1 + // or : MARK + SPACE_0 -> 0 + if (!MATCH_MARK(results->rawbuf[offset++], BIT_MARK)) return false ; + + // IR data is big-endian, so we shuffle it in from the right: + if (MATCH_SPACE(results->rawbuf[offset], ONE_SPACE)) data = (data << 1) | 1 ; + else if (MATCH_SPACE(results->rawbuf[offset], ZERO_SPACE)) data = (data << 1) | 0 ; + else return false ; + offset++; + } + + // Success + results->bits = BITS; + results->value = data; + results->decode_type = DENON; + return true; +} +#endif diff --git a/ir_Template.cpp b/ir_Template.cpp index c0f9606..474d777 100644 --- a/ir_Template.cpp +++ b/ir_Template.cpp @@ -102,16 +102,16 @@ Regards, // //============================================================================== -#define SHUZU_BITS 32 // The number of bits in the command +#define BITS 32 // The number of bits in the command -#define SHUZU_HDR_MARK 1000 // The length of the Header:Mark -#define SHUZU_HDR_SPACE 2000 // The lenght of the Header:Space +#define HDR_MARK 1000 // The length of the Header:Mark +#define HDR_SPACE 2000 // The lenght of the Header:Space -#define SHUZU_BIT_MARK 3000 // The length of a Bit:Mark -#define SHUZU_ONE_SPACE 4000 // The length of a Bit:Space for 1's -#define SHUZU_ZERO_SPACE 5000 // The length of a Bit:Space for 0's +#define BIT_MARK 3000 // The length of a Bit:Mark +#define ONE_SPACE 4000 // The length of a Bit:Space for 1's +#define ZERO_SPACE 5000 // The length of a Bit:Space for 0's -#define SHUZU_OTHER 1234 // Other things you may need to define +#define OTHER 1234 // Other things you may need to define //+============================================================================= // @@ -122,22 +122,22 @@ void IRsend::sendShuzu (unsigned long data, int nbits) enableIROut(38); // Header - mark (SHUZU_HDR_MARK); - space(SHUZU_HDR_SPACE); + mark (HDR_MARK); + space(HDR_SPACE); // Data for (unsigned long mask = 1 << (nbits - 1); mask; mask >>= 1) { if (data & mask) { - mark (SHUZU_BIT_MARK); - space(SHUZU_ONE_SPACE); + mark (BIT_MARK); + space(ONE_SPACE); } else { - mark (SHUZU_BIT_MARK); - space(SHUZU_ZERO_SPACE); + mark (BIT_MARK); + space(ZERO_SPACE); } } // Footer - mark(SHUZU_BIT_MARK); + mark(BIT_MARK); space(0); // Always end with the LED off } #endif @@ -151,27 +151,27 @@ bool IRrecv::decodeShuzu (decode_results *results) int offset = 1; // Skip the Gap reading // Check we have the right amount of data - if (irparams.rawlen != 1 + 2 + (2 * SHUZU_BITS) + 1) return false ; + if (irparams.rawlen != 1 + 2 + (2 * BITS) + 1) return false ; // Check initial Mark+Space match - if (!MATCH_MARK (results->rawbuf[offset++], SHUZU_HDR_MARK )) return false ; - if (!MATCH_SPACE(results->rawbuf[offset++], SHUZU_HDR_SPACE)) return false ; + if (!MATCH_MARK (results->rawbuf[offset++], HDR_MARK )) return false ; + if (!MATCH_SPACE(results->rawbuf[offset++], HDR_SPACE)) return false ; // Read the bits in for (int i = 0; i < SHUZU_BITS; i++) { // Each bit looks like: MARK + SPACE_1 -> 1 // or : MARK + SPACE_0 -> 0 - if (!MATCH_MARK(results->rawbuf[offset++], SAMSUNG_BIT_MARK)) return false ; + if (!MATCH_MARK(results->rawbuf[offset++], BIT_MARK)) return false ; // IR data is big-endian, so we shuffle it in from the right: - if (MATCH_SPACE(results->rawbuf[offset], SHUZU_ONE_SPACE)) data = (data << 1) | 1 ; - else if (MATCH_SPACE(results->rawbuf[offset], SHUZU_ZERO_SPACE)) data = (data << 1) | 0 ; - else return false ; + if (MATCH_SPACE(results->rawbuf[offset], ONE_SPACE)) data = (data << 1) | 1 ; + else if (MATCH_SPACE(results->rawbuf[offset], ZERO_SPACE)) data = (data << 1) | 0 ; + else return false ; offset++; } // Success - results->bits = SHUZU_BITS; + results->bits = BITS; results->value = data; results->decode_type = SHUZU; return true;