Skip to content

Commit

Permalink
Add basic support for HITACHI_AC264 264bit protocol. (#1730)
Browse files Browse the repository at this point in the history
* Add send (`sendHitachiAc264()`) & decode support.
* Add unit tests coverage including real world data.
* Fix up some typos.
* Minor refactor of some code.

For #1729
  • Loading branch information
crankyoldgit authored Jan 9, 2022
1 parent d3c8abc commit 93af543
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 28 deletions.
6 changes: 6 additions & 0 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,12 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
if (decodeHitachiAC(results, offset, kHitachiAc344Bits, true, false))
return true;
#endif // DECODE_HITACHI_AC344
#if DECODE_HITACHI_AC264
// HitachiAC264 should be checked before HitachiAC
DPRINTLN("Attempting Hitachi AC264 decode");
if (decodeHitachiAC(results, offset, kHitachiAc264Bits, true, false))
return true;
#endif // DECODE_HITACHI_AC264
#if DECODE_HITACHI_AC2
// HitachiAC2 should be checked before HitachiAC
DPRINTLN("Attempting Hitachi AC2 decode");
Expand Down
6 changes: 4 additions & 2 deletions src/IRrecv.h
Original file line number Diff line number Diff line change
Expand Up @@ -590,11 +590,13 @@ class IRrecv {
const uint16_t nbits = kHaierAC176Bits,
const bool strict = true);
#endif // DECODE_HAIER_AC176
#if (DECODE_HITACHI_AC || DECODE_HITACHI_AC2 || DECODE_HITACHI_AC344)
#if (DECODE_HITACHI_AC || DECODE_HITACHI_AC2 || DECODE_HITACHI_AC264 || \
DECODE_HITACHI_AC344)
bool decodeHitachiAC(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kHitachiAcBits,
const bool strict = true, const bool MSBfirst = true);
#endif
#endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC2 || DECODE_HITACHI_AC264 ||
// DECODE_HITACHI_AC344)
#if DECODE_HITACHI_AC1
bool decodeHitachiAC1(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kHitachiAc1Bits,
Expand Down
14 changes: 12 additions & 2 deletions src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,13 @@
#define SEND_HITACHI_AC3 _IR_ENABLE_DEFAULT_
#endif // SEND_HITACHI_AC3

#ifndef DECODE_HITACHI_AC264
#define DECODE_HITACHI_AC264 _IR_ENABLE_DEFAULT_
#endif // DECODE_HITACHI_AC264
#ifndef SEND_HITACHI_AC264
#define SEND_HITACHI_AC264 _IR_ENABLE_DEFAULT_
#endif // SEND_HITACHI_AC264

#ifndef DECODE_HITACHI_AC344
#define DECODE_HITACHI_AC344 _IR_ENABLE_DEFAULT_
#endif // DECODE_HITACHI_AC344
Expand Down Expand Up @@ -854,7 +861,7 @@
DECODE_HITACHI_AC344 || DECODE_CORONA_AC || DECODE_SANYO_AC || \
DECODE_VOLTAS || DECODE_MIRAGE || DECODE_HAIER_AC176 || \
DECODE_TEKNOPOINT || DECODE_KELON || DECODE_TROTEC_3550 || \
DECODE_SANYO_AC88 || DECODE_RHOSS || \
DECODE_SANYO_AC88 || DECODE_RHOSS || DECODE_HITACHI_AC264 || \
false)
// Add any DECODE to the above if it uses result->state (see kStateSizeMax)
// you might also want to add the protocol to hasACState function
Expand Down Expand Up @@ -1005,8 +1012,9 @@ enum decode_type_t {
RHOSS,
AIRTON,
COOLIX48, // 110
HITACHI_AC264,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = COOLIX48,
kLastDecodeType = HITACHI_AC264,
};

// Message lengths & required repeat values
Expand Down Expand Up @@ -1116,6 +1124,8 @@ const uint16_t kHitachiAc3StateLength = 27;
const uint16_t kHitachiAc3Bits = kHitachiAc3StateLength * 8;
const uint16_t kHitachiAc3MinStateLength = 15;
const uint16_t kHitachiAc3MinBits = kHitachiAc3MinStateLength * 8;
const uint16_t kHitachiAc264StateLength = 33;
const uint16_t kHitachiAc264Bits = kHitachiAc264StateLength * 8;
const uint16_t kHitachiAc344StateLength = 43;
const uint16_t kHitachiAc344Bits = kHitachiAc344StateLength * 8;
const uint16_t kHitachiAc424StateLength = 53;
Expand Down
7 changes: 7 additions & 0 deletions src/IRsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
return kHitachiAc2Bits;
case HITACHI_AC3:
return kHitachiAc3Bits;
case HITACHI_AC264:
return kHitachiAc264Bits;
case HITACHI_AC344:
return kHitachiAc344Bits;
case HITACHI_AC424:
Expand Down Expand Up @@ -1210,6 +1212,11 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state,
sendHitachiAc3(state, nbytes);
break;
#endif // SEND_HITACHI_AC3
#if SEND_HITACHI_AC264
case HITACHI_AC264:
sendHitachiAc264(state, nbytes);
break;
#endif // SEND_HITACHI_AC264
#if SEND_HITACHI_AC344
case HITACHI_AC344:
sendHitachiAc344(state, nbytes);
Expand Down
5 changes: 5 additions & 0 deletions src/IRsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,11 @@ class IRsend {
// different sizes
const uint16_t repeat = kHitachiAcDefaultRepeat);
#endif // SEND_HITACHI_AC3
#if SEND_HITACHI_AC264
void sendHitachiAc264(const unsigned char data[],
const uint16_t nbytes = kHitachiAc264StateLength,
const uint16_t repeat = kHitachiAcDefaultRepeat);
#endif // SEND_HITACHI_AC264
#if SEND_HITACHI_AC344
void sendHitachiAc344(const unsigned char data[],
const uint16_t nbytes = kHitachiAc344StateLength,
Expand Down
1 change: 1 addition & 0 deletions src/IRtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
D_STR_RHOSS "\x0"
D_STR_AIRTON "\x0"
D_STR_COOLIX48 "\x0"
D_STR_HITACHI_AC264 "\x0"
///< New protocol strings should be added just above this line.
"\x0" ///< This string requires double null termination.
};
Expand Down
1 change: 1 addition & 0 deletions src/IRutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ bool hasACState(const decode_type_t protocol) {
case HITACHI_AC1:
case HITACHI_AC2:
case HITACHI_AC3:
case HITACHI_AC264:
case HITACHI_AC344:
case HITACHI_AC424:
case KELVINATOR:
Expand Down
76 changes: 57 additions & 19 deletions src/ir_Hitachi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ using irutils::checkInvertedBytePairs;
using irutils::invertBytePairs;
using irutils::minsToString;

#if (SEND_HITACHI_AC || SEND_HITACHI_AC2 || SEND_HITACHI_AC344)
#if (SEND_HITACHI_AC || SEND_HITACHI_AC2 || SEND_HITACHI_AC264 || \
SEND_HITACHI_AC344)
/// Send a Hitachi 28-byte/224-bit A/C formatted message. (HITACHI_AC)
/// Status: STABLE / Working.
/// @param[in] data The message to be sent.
Expand All @@ -68,21 +69,28 @@ void IRsend::sendHitachiAC(const unsigned char data[], const uint16_t nbytes,
if (nbytes < kHitachiAcStateLength)
return; // Not enough bytes to send a proper message.

const bool MSBfirst = (nbytes == kHitachiAc344StateLength) ? false : true;
bool MSBfirst = true;
switch (nbytes) {
case kHitachiAc264StateLength:
case kHitachiAc344StateLength:
MSBfirst = false;
}

sendGeneric(kHitachiAcHdrMark, kHitachiAcHdrSpace, kHitachiAcBitMark,
kHitachiAcOneSpace, kHitachiAcBitMark, kHitachiAcZeroSpace,
kHitachiAcBitMark, kHitachiAcMinGap, data, nbytes, 38, MSBfirst,
repeat, 50);
}
#endif // (SEND_HITACHI_AC || SEND_HITACHI_AC2 || SEND_HITACHI_AC344)
#endif // (SEND_HITACHI_AC || SEND_HITACHI_AC2 || SEND_HITACHI_AC264 ||
// SEND_HITACHI_AC344)

#if SEND_HITACHI_AC1
/// Send a Hitachi 13 byte/224-bit A/C formatted message. (HITACHI_AC1)
/// Status: STABLE / Confirmed Working.
/// @param[in] data The message to be sent.
/// @param[in] nbytes The number of bytes of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
/// @note Basically the same as sendHitatchiAC() except different size & header.
/// @note Basically the same as sendHitachiAC() except different size & header.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/453
void IRsend::sendHitachiAC1(const unsigned char data[], const uint16_t nbytes,
const uint16_t repeat) {
Expand All @@ -97,7 +105,7 @@ void IRsend::sendHitachiAC1(const unsigned char data[], const uint16_t nbytes,

#if SEND_HITACHI_AC2
/// Send a Hitachi 53 byte/424-bit A/C formatted message. (HITACHI_AC2)
/// Basically the same as sendHitatchiAC() except different size.
/// Basically the same as sendHitachiAC() except different size.
/// Status: STABLE / Expected to work.
/// @param[in] data The message to be sent.
/// @param[in] nbytes The number of bytes of message to be sent.
Expand All @@ -112,7 +120,7 @@ void IRsend::sendHitachiAC2(const unsigned char data[], const uint16_t nbytes,

#if SEND_HITACHI_AC344
/// Send a Hitachi A/C 43-byte/344-bit message. (HITACHI_AC344)
/// Basically the same as sendHitatchiAC() except different size.
/// Basically the same as sendHitachiAC() except different size.
/// Status: Beta / Probably works.
/// @param[in] data An array of bytes containing the IR command.
/// @param[in] nbytes Nr. of bytes of data in the array.
Expand Down Expand Up @@ -827,22 +835,23 @@ String IRHitachiAc1::toString(void) const {
}

#if (DECODE_HITACHI_AC || DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2 || \
DECODE_HITACHI_AC344)
DECODE_HITACHI_AC344 || DECODE_HITACHI_AC264)
/// Decode the supplied Hitachi A/C message.
/// Status: STABLE / Expected to work.
/// @param[in,out] results Ptr to the data to decode & where to store the result
/// @param[in] offset The starting index to use when attempting to decode the
/// raw data. Typically/Defaults to kStartOffset.
/// @param[in] nbits The number of data bits to expect.
/// Typically kHitachiAcBits, kHitachiAc1Bits, kHitachiAc2Bits,
/// kHitachiAc344Bits
/// kHitachiAc344Bits, kHitachiAc264Bits
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @param[in] MSBfirst Is the data per byte stored in MSB First (true) or
/// LSB First order(false)?
/// @return True if it can decode it, false if it can't.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/417
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/453
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1134
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1729
bool IRrecv::decodeHitachiAC(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict,
const bool MSBfirst) {
Expand All @@ -853,6 +862,7 @@ bool IRrecv::decodeHitachiAC(decode_results *results, uint16_t offset,
case kHitachiAcBits:
case kHitachiAc1Bits:
case kHitachiAc2Bits:
case kHitachiAc264Bits:
case kHitachiAc344Bits:
break; // Okay to continue.
default:
Expand All @@ -879,16 +889,20 @@ bool IRrecv::decodeHitachiAC(decode_results *results, uint16_t offset,

// Compliance
if (strict) {
if (nbits / 8 == kHitachiAcStateLength &&
!IRHitachiAc::validChecksum(results->state, kHitachiAcStateLength))
return false;
if (nbits / 8 == kHitachiAc1StateLength &&
!IRHitachiAc1::validChecksum(results->state, kHitachiAc1StateLength))
return false;
if (nbits / 8 == kHitachiAc344StateLength &&
!IRHitachiAc3::hasInvertedStates(results->state,
kHitachiAc344StateLength))
return false;
const uint16_t nbytes = nbits / 8;
switch (nbytes) {
case kHitachiAcStateLength:
if (!IRHitachiAc::validChecksum(results->state, nbytes)) return false;
break;
case kHitachiAc1StateLength:
if (!IRHitachiAc1::validChecksum(results->state, nbytes)) return false;
break;
case kHitachiAc264StateLength:
case kHitachiAc344StateLength:
if (!IRHitachiAc3::hasInvertedStates(results->state, nbytes))
return false;
break;
}
}

// Success
Expand All @@ -899,6 +913,9 @@ bool IRrecv::decodeHitachiAC(decode_results *results, uint16_t offset,
case kHitachiAc2Bits:
results->decode_type = decode_type_t::HITACHI_AC2;
break;
case kHitachiAc264Bits:
results->decode_type = decode_type_t::HITACHI_AC264;
break;
case kHitachiAc344Bits:
results->decode_type = decode_type_t::HITACHI_AC344;
break;
Expand All @@ -913,7 +930,7 @@ bool IRrecv::decodeHitachiAC(decode_results *results, uint16_t offset,
return true;
}
#endif // (DECODE_HITACHI_AC || DECODE_HITACHI_AC1 || DECODE_HITACHI_AC2 ||
// DECODE_HITACHI_AC344)
// DECODE_HITACHI_AC344 || DECODE_HITACHI_AC264)

#if SEND_HITACHI_AC424
/// Send a Hitachi 53-byte/424-bit A/C formatted message. (HITACHI_AC424)
Expand Down Expand Up @@ -1578,3 +1595,24 @@ String IRHitachiAc344::toString(void) const {
result += ')';
return result;
}


#if SEND_HITACHI_AC264
/// Send a Hitachi 33-byte/264-bit A/C message (HITACHI_AC264)
/// Basically the same as sendHitachiAC() except different size.
/// Status: STABLE / Reported as working.
/// @param[in] data An array of bytes containing the IR command.
/// @param[in] nbytes Nr. of bytes of data in the array.
/// @param[in] repeat Nr. of times the message is to be repeated. (Default = 0).
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1729
void IRsend::sendHitachiAc264(const unsigned char data[], const uint16_t nbytes,
const uint16_t repeat) {
if (nbytes < kHitachiAc264StateLength)
return; // Not enough bytes to send a proper message.
sendHitachiAC(data, nbytes, repeat);
}
#endif // SEND_HITACHI_AC264

#if DECODE_HITACHI_AC264
// For Decoding HITACHI_AC264, see `decodeHitachiAC`
#endif // DECODE_HITACHI_AC264
3 changes: 3 additions & 0 deletions src/ir_Hitachi.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1056
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1060
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1134
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1729

// Supports:
// Brand: Hitachi, Model: RAS-35THA6 remote
Expand All @@ -19,6 +20,8 @@
// Brand: Hitachi, Model: R-LT0541-HTA/Y.K.1.1-1 V2.3 remote (HITACHI_AC1)
// Brand: Hitachi, Model: RAS-22NK A/C (HITACHI_AC344)
// Brand: Hitachi, Model: RF11T1 remote (HITACHI_AC344)
// Brand: Hitachi, Model: RAR-2P2 remote (HITACHI_AC264)
// Brand: Hitachi, Model: RAK-25NH5 A/C (HITACHI_AC264)

#ifndef IR_HITACHI_H_
#define IR_HITACHI_H_
Expand Down
13 changes: 8 additions & 5 deletions src/locale/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -800,19 +800,22 @@ D_STR_INDIRECT " " D_STR_MODE
#define D_STR_HITACHI_AC "HITACHI_AC"
#endif // D_STR_HITACHI_AC
#ifndef D_STR_HITACHI_AC1
#define D_STR_HITACHI_AC1 "HITACHI_AC1"
#define D_STR_HITACHI_AC1 D_STR_HITACHI_AC "1"
#endif // D_STR_HITACHI_AC1
#ifndef D_STR_HITACHI_AC2
#define D_STR_HITACHI_AC2 "HITACHI_AC2"
#define D_STR_HITACHI_AC2 D_STR_HITACHI_AC "2"
#endif // D_STR_HITACHI_AC2
#ifndef D_STR_HITACHI_AC3
#define D_STR_HITACHI_AC3 "HITACHI_AC3"
#define D_STR_HITACHI_AC3 D_STR_HITACHI_AC "3"
#endif // D_STR_HITACHI_AC3
#ifndef D_STR_HITACHI_AC264
#define D_STR_HITACHI_AC264 D_STR_HITACHI_AC "264"
#endif // D_STR_HITACHI_AC264
#ifndef D_STR_HITACHI_AC344
#define D_STR_HITACHI_AC344 "HITACHI_AC344"
#define D_STR_HITACHI_AC344 D_STR_HITACHI_AC "344"
#endif // D_STR_HITACHI_AC344
#ifndef D_STR_HITACHI_AC424
#define D_STR_HITACHI_AC424 "HITACHI_AC424"
#define D_STR_HITACHI_AC424 D_STR_HITACHI_AC "424"
#endif // D_STR_HITACHI_AC424
#ifndef D_STR_INAX
#define D_STR_INAX "INAX"
Expand Down
Loading

0 comments on commit 93af543

Please sign in to comment.