// Decode the supplied Whynter message. // // Args: // results: Ptr to the data to decode and where to store the decode result. // nbits: Nr. of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // // Status: BETA Strict mode is ALPHA. // // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp bool IRrecv::decodeWhynter(decode_results *results, uint16_t nbits, bool strict) { if (results->rawlen < 2 * nbits + 2 * HEADER + FOOTER - 1) return false; // We don't have enough entries to possibly match. // Compliance if (strict && nbits != WHYNTER_BITS) return false; // Incorrect nr. of bits per spec. uint16_t offset = OFFSET_START; // Header // Sequence begins with a bit mark and a zero space. // These are typically small, so we'll prefer to do the calibration // on the much larger header mark & space that are next. if (!matchMark(results->rawbuf[offset++], WHYNTER_BIT_MARK)) return false; if (!matchSpace(results->rawbuf[offset++], WHYNTER_ZERO_SPACE)) return false; // Main header mark and space if (!matchMark(results->rawbuf[offset], WHYNTER_HDR_MARK)) return false; // Calculate how long the common tick time is based on the header mark. uint32_t m_tick = results->rawbuf[offset++] * RAWTICK / WHYNTER_HDR_MARK_TICKS; if (!matchSpace(results->rawbuf[offset], WHYNTER_HDR_SPACE)) return false; // Calculate how long the common tick time is based on the header space. uint32_t s_tick = results->rawbuf[offset++] * RAWTICK / WHYNTER_HDR_SPACE_TICKS; // Data uint64_t data = 0; match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, WHYNTER_BIT_MARK_TICKS * m_tick, WHYNTER_ONE_SPACE_TICKS * s_tick, WHYNTER_BIT_MARK_TICKS * m_tick, WHYNTER_ZERO_SPACE_TICKS * s_tick); if (data_result.success == false) return false; data = data_result.data; offset += data_result.used; // Footer if (!matchMark(results->rawbuf[offset++], WHYNTER_BIT_MARK_TICKS * m_tick)) return false; if (offset < results->rawlen && !matchAtLeast(results->rawbuf[offset], WHYNTER_MIN_GAP_TICKS * s_tick)) return false; // Success results->decode_type = WHYNTER; results->bits = nbits; results->value = data; results->address = 0; results->command = 0; return true; }
// Decode the supplied Whynter message. // // Args: // results: Ptr to the data to decode and where to store the decode result. // nbits: Nr. of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // // Status: BETA Strict mode is ALPHA. // // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp bool IRrecv::decodeWhynter(decode_results *results, uint16_t nbits, bool strict) { if (results->rawlen < 2 * nbits + 2 * kHeader + kFooter - 1) return false; // We don't have enough entries to possibly match. // Compliance if (strict && nbits != kWhynterBits) return false; // Incorrect nr. of bits per spec. uint16_t offset = kStartOffset; // Header // Sequence begins with a bit mark and a zero space. // These are typically small, so we'll prefer to do the calibration // on the much larger header mark & space that are next. if (!matchMark(results->rawbuf[offset++], kWhynterBitMark)) return false; if (!matchSpace(results->rawbuf[offset++], kWhynterZeroSpace)) return false; // Main header mark and space if (!matchMark(results->rawbuf[offset], kWhynterHdrMark)) return false; // Calculate how long the common tick time is based on the header mark. uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kWhynterHdrMarkTicks; if (!matchSpace(results->rawbuf[offset], kWhynterHdrSpace)) return false; // Calculate how long the common tick time is based on the header space. uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kWhynterHdrSpaceTicks; // Data uint64_t data = 0; match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, kWhynterBitMarkTicks * m_tick, kWhynterOneSpaceTicks * s_tick, kWhynterBitMarkTicks * m_tick, kWhynterZeroSpaceTicks * s_tick); if (data_result.success == false) return false; data = data_result.data; offset += data_result.used; // Footer if (!matchMark(results->rawbuf[offset++], kWhynterBitMarkTicks * m_tick)) return false; if (offset < results->rawlen && !matchAtLeast(results->rawbuf[offset], kWhynterMinGapTicks * s_tick)) return false; // Success results->decode_type = WHYNTER; results->bits = nbits; results->value = data; results->address = 0; results->command = 0; return true; }
// Decode the supplied Mitsubishi message. // // Args: // results: Ptr to the data to decode and where to store the decode result. // nbits: Nr. of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // // Status: BETA / previously working. // // Notes: // This protocol appears to have no header. // // Ref: // GlobalCache's Control Tower's Mitsubishi TV data. bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t nbits, bool strict) { if (results->rawlen < 2 * nbits + FOOTER - 1) return false; // Shorter than shortest possibly expected. if (strict && nbits != MITSUBISHI_BITS) return false; // Request is out of spec. uint16_t offset = OFFSET_START; uint64_t data = 0; // No Header // Data uint16_t actualBits; for (actualBits = 0; actualBits < nbits; actualBits++, offset++) { if (!matchMark(results->rawbuf[offset++], MITSUBISHI_BIT_MARK, 30)) return false; if (matchSpace(results->rawbuf[offset], MITSUBISHI_ONE_SPACE)) data = (data << 1) | 1; // 1 else if (matchSpace(results->rawbuf[offset], MITSUBISHI_ZERO_SPACE)) data <<= 1; // 0 else break; } // Footer if (!matchMark(results->rawbuf[offset++], MITSUBISHI_BIT_MARK, 30)) return false; if (offset < results->rawlen && !matchAtLeast(results->rawbuf[offset], MITSUBISHI_MIN_GAP)) return false; // Compliance if (actualBits < nbits) return false; if (strict && actualBits != nbits) return false; // Not as we expected. // Success results->decode_type = MITSUBISHI; results->bits = actualBits; results->value = data; results->address = 0; results->command = 0; return true; }
// Decode a Denon message. // // Args: // results: Ptr to the data to decode and where to store the decode result. // nbits: Expected nr. of data bits. (Typically DENON_BITS) // Returns: // boolean: True if it can decode it, false if it can't. // // Status: BETA / Should work fine. // // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Denon.cpp bool IRrecv::decodeDenon(decode_results *results, uint16_t nbits, bool strict) { // Compliance if (strict) { switch (nbits) { case DENON_BITS: case DENON_48_BITS: case kDenonLegacyBits: break; default: return false; } } // Denon uses the Sharp & Panasonic(Kaseikyo) protocol for some // devices, so check for those first. // It is not exactly like Sharp's protocols, but close enough. // e.g. The expansion bit is not set for Denon vs. set for Sharp. // Ditto for Panasonic, it's the same except for a different // manufacturer code. if (!decodeSharp(results, nbits, true, false) && !decodePanasonic(results, nbits, true, kDenonManufacturer)) { // We couldn't decode it as expected, so try the old legacy method. // NOTE: I don't think this following protocol actually exists. // Looks like a partial version of the Sharp protocol. // Check we have enough data if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false; if (strict && nbits != kDenonLegacyBits) return false; uint64_t data = 0; uint16_t offset = kStartOffset; // Header if (!matchMark(results->rawbuf[offset], kDenonHdrMark)) return false; // Calculate how long the common tick time is based on the header mark. uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kDenonHdrMarkTicks; if (!matchSpace(results->rawbuf[offset], kDenonHdrSpace)) return false; uint32_t s_tick = results->rawbuf[offset++] * kRawTick / kDenonHdrSpaceTicks; // Data match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits, kDenonBitMarkTicks * m_tick, kDenonOneSpaceTicks * s_tick, kDenonBitMarkTicks * m_tick, kDenonZeroSpaceTicks * s_tick); if (data_result.success == false) return false; data = data_result.data; offset += data_result.used; // Footer if (!matchMark(results->rawbuf[offset++], kDenonBitMarkTicks * m_tick)) return false; // Success results->bits = nbits; results->value = data; results->address = 0; results->command = 0; } // Legacy decode. // Compliance if (strict && nbits != results->bits) return false; // Success results->decode_type = DENON; return true; }
// Decode a Philips RC-MM packet (between 12 & 32 bits) if possible. // Places successful decode information in the results pointer. // Args: // results: Ptr to the data to decode and where to store the decode result. // nbits: Nr. of bits to expect in the data portion. Typically RCMM_BITS. // strict: Flag to indicate if we strictly adhere to the specification. // Returns: // boolean: True if it can decode it, false if it can't. // // Status: BETA / Should be working. // // Ref: // http://www.sbprojects.com/knowledge/ir/rcmm.php bool IRrecv::decodeRCMM(decode_results *results, uint16_t nbits, bool strict) { uint64_t data = 0; uint16_t offset = OFFSET_START; if (results->rawlen <= 4) return false; // Not enough entries to ever be RCMM. // Calc the maximum size in bits, the message can be, or that we can accept. int16_t maxBitSize = std::min((uint16_t) results->rawlen - 4, (uint16_t) sizeof(data) * 8); // Compliance if (strict) { // Technically the spec says bit sizes should be 12 xor 24. however // 32 bits has been seen from a device. We are going to assume // 12 <= bits <= 32 is the 'required' bit length for the spec. if (maxBitSize < 12 || maxBitSize > 32) return false; if (maxBitSize < nbits) return false; // Short cut, we can never reach the expected nr. of bits. } // Header decode if (!matchMark(results->rawbuf[offset++], RCMM_HDR_MARK)) return false; if (!matchSpace(results->rawbuf[offset++], RCMM_HDR_SPACE)) return false; // Data decode // RC-MM has two bits of data per mark/space pair. uint16_t actualBits; for (actualBits = 0; actualBits < maxBitSize; actualBits += 2, offset++) { if (!matchMark(results->rawbuf[offset++], RCMM_BIT_MARK)) return false; data <<= 2; // Use non-default tolerance & excess for matching some of the spaces as the // defaults are too generous and causes mis-matches in some cases. if (matchSpace(results->rawbuf[offset], RCMM_BIT_SPACE_0, TOLERANCE, RCMM_EXCESS)) data += 0; else if (matchSpace(results->rawbuf[offset], RCMM_BIT_SPACE_1, TOLERANCE, RCMM_EXCESS)) data += 1; else if (matchSpace(results->rawbuf[offset], RCMM_BIT_SPACE_2, RCMM_TOLERANCE, RCMM_EXCESS)) data += 2; else if (matchSpace(results->rawbuf[offset], RCMM_BIT_SPACE_3, RCMM_TOLERANCE, RCMM_EXCESS)) data += 3; else return false; } // Footer decode if (!matchMark(results->rawbuf[offset++], RCMM_BIT_MARK)) return false; if (offset < results->rawlen && !matchAtLeast(results->rawbuf[offset], RCMM_MIN_GAP)) return false; // Compliance if (strict && actualBits != nbits) return false; // Success results->value = data; results->decode_type = RCMM; results->bits = actualBits; results->address = 0; results->command = 0; return true; }