Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CARRIER_AC128: Experimental Basic support for Carrier AC 128bit protocol. #1798

Merged
merged 1 commit into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
DPRINTLN("Attempting Haier AC 160 bit decode");
if (decodeHaierAC160(results, offset)) return true;
#endif // DECODE_HAIER_AC160
#if DECODE_CARRIER_AC128
DPRINTLN("Attempting Carrier AC 128-bit decode");
if (decodeCarrierAC128(results, offset)) return true;
#endif // DECODE_CARRIER_AC128
// Typically new protocols are added above this line.
}
#if DECODE_HASH
Expand Down
6 changes: 6 additions & 0 deletions src/IRrecv.h
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,12 @@ class IRrecv {
const uint16_t nbits = kCarrierAc64Bits,
const bool strict = true);
#endif // DECODE_CARRIER_AC64
#if DECODE_CARRIER_AC128
bool decodeCarrierAC128(decode_results *results,
uint16_t offset = kStartOffset,
const uint16_t nbits = kCarrierAc128Bits,
const bool strict = true);
#endif // DECODE_CARRIER_AC128
#if DECODE_GOODWEATHER
bool decodeGoodweather(decode_results *results,
uint16_t offset = kStartOffset,
Expand Down
15 changes: 13 additions & 2 deletions src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,13 @@
#define SEND_CARRIER_AC64 _IR_ENABLE_DEFAULT_
#endif // SEND_CARRIER_AC64

#ifndef DECODE_CARRIER_AC128
#define DECODE_CARRIER_AC128 _IR_ENABLE_DEFAULT_
#endif // DECODE_CARRIER_AC128
#ifndef SEND_CARRIER_AC128
#define SEND_CARRIER_AC128 _IR_ENABLE_DEFAULT_
#endif // SEND_CARRIER_AC128

#ifndef DECODE_HAIER_AC
#define DECODE_HAIER_AC _IR_ENABLE_DEFAULT_
#endif // DECODE_HAIER_AC
Expand Down Expand Up @@ -890,7 +897,7 @@
DECODE_VOLTAS || DECODE_MIRAGE || DECODE_HAIER_AC176 || \
DECODE_TEKNOPOINT || DECODE_KELON || DECODE_TROTEC_3550 || \
DECODE_SANYO_AC88 || DECODE_RHOSS || DECODE_HITACHI_AC264 || \
DECODE_KELON168 || DECODE_HITACHI_AC296 || \
DECODE_KELON168 || DECODE_HITACHI_AC296 || DECODE_CARRIER_AC128 || \
DECODE_DAIKIN200 || SEND_HAIER_AC160 || \
false)
// Add any DECODE to the above if it uses result->state (see kStateSizeMax)
Expand Down Expand Up @@ -1047,8 +1054,9 @@ enum decode_type_t {
HITACHI_AC296,
DAIKIN200,
HAIER_AC160, // 115
CARRIER_AC128,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = HAIER_AC160,
kLastDecodeType = CARRIER_AC128,
};

// Message lengths & required repeat values
Expand Down Expand Up @@ -1078,6 +1086,9 @@ const uint16_t kCarrierAc40Bits = 40;
const uint16_t kCarrierAc40MinRepeat = 2;
const uint16_t kCarrierAc64Bits = 64;
const uint16_t kCarrierAc64MinRepeat = kNoRepeat;
const uint16_t kCarrierAc128StateLength = 16;
const uint16_t kCarrierAc128Bits = kCarrierAc128StateLength * 8;
const uint16_t kCarrierAc128MinRepeat = kNoRepeat;
const uint16_t kCoronaAcStateLengthShort = 7;
const uint16_t kCoronaAcStateLength = kCoronaAcStateLengthShort * 3;
const uint16_t kCoronaAcBitsShort = kCoronaAcStateLengthShort * 8;
Expand Down
7 changes: 7 additions & 0 deletions src/IRsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
return kArgoBits;
case CORONA_AC:
return kCoronaAcBits;
case CARRIER_AC128:
return kCarrierAc128Bits;
case DAIKIN:
return kDaikinBits;
case DAIKIN128:
Expand Down Expand Up @@ -1130,6 +1132,11 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state,
sendArgo(state, nbytes);
break;
#endif // SEND_ARGO
#if SEND_CARRIER_AC128
case CARRIER_AC128:
sendCarrierAC128(state, nbytes);
break;
#endif // SEND_CARRIER_AC128
#if SEND_CORONA_AC
case CORONA_AC:
sendCoronaAc(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 @@ -563,6 +563,11 @@ class IRsend {
void sendCarrierAC64(uint64_t data, uint16_t nbits = kCarrierAc64Bits,
uint16_t repeat = kCarrierAc64MinRepeat);
#endif
#if SEND_CARRIER_AC128
void sendCarrierAC128(const uint8_t data[],
uint16_t nbytes = kCarrierAc128StateLength,
uint16_t repeat = kCarrierAc128MinRepeat);
#endif // SEND_CARRIER_AC128
#if (SEND_HAIER_AC || SEND_HAIER_AC_YRW02 || SEND_HAIER_AC176)
void sendHaierAC(const unsigned char data[],
const uint16_t nbytes = kHaierACStateLength,
Expand Down
1 change: 1 addition & 0 deletions src/IRtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
D_STR_HITACHI_AC296 "\x0"
D_STR_DAIKIN200 "\x0"
D_STR_HAIER_AC160 "\x0"
D_STR_CARRIER_AC128 "\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 @@ -172,6 +172,7 @@ bool hasACState(const decode_type_t protocol) {
// This is kept sorted by name
case AMCOR:
case ARGO:
case CARRIER_AC128:
case CORONA_AC:
case DAIKIN:
case DAIKIN128:
Expand Down
114 changes: 113 additions & 1 deletion src/ir_Carrier.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Copyright 2018, 2020 David Conran
// Copyright 2018-2022 David Conran
/// @file
/// @brief Carrier protocols.
/// @see CarrierAc https://github.com/crankyoldgit/IRremoteESP8266/issues/385
/// @see CarrierAc64 https://github.com/crankyoldgit/IRremoteESP8266/issues/1127
/// @see CarrierAc128 https://github.com/crankyoldgit/IRremoteESP8266/issues/1797

#include "ir_Carrier.h"
#include <algorithm>
Expand Down Expand Up @@ -45,6 +46,16 @@ const uint16_t kCarrierAc64OneSpace = 1736;
const uint16_t kCarrierAc64ZeroSpace = 615;
const uint32_t kCarrierAc64Gap = kDefaultMessageGap; // A guess.

const uint16_t kCarrierAc128HdrMark = 4600;
const uint16_t kCarrierAc128HdrSpace = 2600;
const uint16_t kCarrierAc128Hdr2Mark = 9300;
const uint16_t kCarrierAc128Hdr2Space = 5000;
const uint16_t kCarrierAc128BitMark = 340;
const uint16_t kCarrierAc128OneSpace = 1000;
const uint16_t kCarrierAc128ZeroSpace = 400;
const uint16_t kCarrierAc128SectionGap = 20600;
const uint16_t kCarrierAc128InterSpace = 6700;
const uint16_t kCarrierAc128SectionBits = kCarrierAc128Bits / 2;

#if SEND_CARRIER_AC
/// Send a Carrier HVAC formatted message.
Expand Down Expand Up @@ -533,3 +544,104 @@ stdAc::state_t IRCarrierAc64::toCommon(void) const {
result.clock = -1;
return result;
}

#if SEND_CARRIER_AC128
/// Send a Carrier 128bit HVAC formatted message.
/// Status: BETA / Seems to work with tests. Needs testing agaisnt real devices.
/// @param[in] data The message to be sent.
/// @param[in] nbytes The byte size of the message being sent.
/// @param[in] repeat The number of times the message is to be repeated.
void IRsend::sendCarrierAC128(const uint8_t data[], const uint16_t nbytes,
const uint16_t repeat) {
// Min length check.
if (nbytes <= kCarrierAc128StateLength / 2) return;

enableIROut(kCarrierAcFreq);
// Handle repeats.
for (uint16_t r = 0; r <= repeat; r++) {
// First part of the message.
// Headers + Data + SectionGap
sendGeneric(kCarrierAc128HdrMark, kCarrierAc128HdrSpace,
kCarrierAc128BitMark, kCarrierAc128OneSpace,
kCarrierAc128BitMark, kCarrierAc128ZeroSpace,
kCarrierAc128BitMark, kCarrierAc128SectionGap,
data, nbytes / 2, kCarrierAcFreq, false, 0, kDutyDefault);
// Inter-message markers
mark(kCarrierAc128HdrMark);
space(kCarrierAc128InterSpace);
// Second part of the message
// Headers + Data + SectionGap
sendGeneric(kCarrierAc128Hdr2Mark, kCarrierAc128Hdr2Space,
kCarrierAc128BitMark, kCarrierAc128OneSpace,
kCarrierAc128BitMark, kCarrierAc128ZeroSpace,
kCarrierAc128BitMark, kCarrierAc128SectionGap,
data + (nbytes / 2), nbytes / 2, kCarrierAcFreq,
false, 0, kDutyDefault);
// Footer
mark(kCarrierAc128HdrMark);
space(kDefaultMessageGap);
}
}
#endif // SEND_CARRIER_AC128

#if DECODE_CARRIER_AC128
/// Decode the supplied Carrier 128-bit HVAC message.
/// Status: STABLE / Expected to work.
/// @param[in,out] results Ptr to the data to decode & where to store the decode
/// 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.
/// @param[in] strict Flag indicating if we should perform strict matching.
/// @return A boolean. True if it can decode it, false if it can't.
bool IRrecv::decodeCarrierAC128(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (results->rawlen < 2 * (nbits + 2 * kHeader + kFooter) - 1 + offset)
return false; // Can't possibly be a valid Carrier message.
if (strict && nbits != kCarrierAc128Bits)
return false; // We expect Carrier to be 128 bits of message.

uint16_t used;
uint16_t pos = 0;
const uint16_t sectionbits = nbits / 2;
// Match the first section.
used = matchGeneric(results->rawbuf + offset, results->state,
results->rawlen - offset, sectionbits,
kCarrierAc128HdrMark, kCarrierAc128HdrSpace,
kCarrierAc128BitMark, kCarrierAc128OneSpace,
kCarrierAc128BitMark, kCarrierAc128ZeroSpace,
kCarrierAc128BitMark, kCarrierAc128SectionGap, true,
kUseDefTol, kMarkExcess, false);
if (used == 0) return false; // No match.
offset += used;
pos += sectionbits / 8;
// Look for the inter-message markers.
if (!matchMark(results->rawbuf[offset++], kCarrierAc128HdrMark))
return false;
if (!matchSpace(results->rawbuf[offset++], kCarrierAc128InterSpace))
return false;
// Now look for the second section.
used = matchGeneric(results->rawbuf + offset, results->state + pos,
results->rawlen - offset, sectionbits,
kCarrierAc128Hdr2Mark, kCarrierAc128Hdr2Space,
kCarrierAc128BitMark, kCarrierAc128OneSpace,
kCarrierAc128BitMark, kCarrierAc128ZeroSpace,
kCarrierAc128BitMark, kCarrierAc128SectionGap, true,
kUseDefTol, kMarkExcess, false);
if (used == 0) return false; // No match.
offset += used;
// Now check for the Footer.
if (!matchMark(results->rawbuf[offset++], kCarrierAc128HdrMark)) return false;
if (offset < results->rawlen &&
!matchAtLeast(results->rawbuf[offset], kDefaultMessageGap)) return false;


// Compliance
// if (strict && !IRCarrierAc128::validChecksum(results->value)) return false;

// Success
results->bits = nbits;
results->decode_type = CARRIER_AC128;
return true;
}
#endif // DECODE_CARRIER_AC128
4 changes: 3 additions & 1 deletion src/ir_Carrier.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Copyright 2020 David Conran
// Copyright 2020-2022 David Conran
/// @file
/// @brief Carrier A/C
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1127
/// @see https://docs.google.com/spreadsheets/d/1EZy78L0cn1KDIX1aKq2biptejFqCjD5HO3tLiRvXf48/edit#gid=0
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1797

// Supports:
// Brand: Carrier/Surrey, Model: 42QG5A55970 remote
Expand All @@ -11,6 +12,7 @@
// Brand: Carrier/Surrey, Model: 619EGX0180E0 A/C
// Brand: Carrier/Surrey, Model: 619EGX0220E0 A/C
// Brand: Carrier/Surrey, Model: 53NGK009/012 Inverter
// Brand: Carrier, Model: 40GKX0E2006 remote (CARRIER_AC128)

#ifndef IR_CARRIER_H_
#define IR_CARRIER_H_
Expand Down
3 changes: 3 additions & 0 deletions src/locale/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,9 @@ D_STR_INDIRECT " " D_STR_MODE
#ifndef D_STR_CARRIER_AC64
#define D_STR_CARRIER_AC64 D_STR_CARRIER_AC "64"
#endif // D_STR_CARRIER_AC64
#ifndef D_STR_CARRIER_AC128
#define D_STR_CARRIER_AC128 D_STR_CARRIER_AC "128"
#endif // D_STR_CARRIER_AC128
#ifndef D_STR_COOLIX
#define D_STR_COOLIX "COOLIX"
#endif // D_STR_COOLIX
Expand Down
Loading