Skip to content

Commit e7824c4

Browse files
authored
Experimental basic support for Carrier 84-bit protocol. (#1945)
* Add `sendCarrierAC84()` and `decodeCarrierAC84()` routines. * Create some unit tests to cover the new code. * Hack in some support for non-byte-aligned > 64 bit protocols. * Update supported devices. For #1943
1 parent 406a817 commit e7824c4

File tree

12 files changed

+272
-7
lines changed

12 files changed

+272
-7
lines changed

src/IRrecv.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
11731173
DPRINTLN("Attempting WOWWEE decode");
11741174
if (decodeWowwee(results, offset)) return true;
11751175
#endif // DECODE_WOWWEE
1176+
#if DECODE_CARRIER_AC84
1177+
DPRINTLN("Attempting Carrier A/C 84-bit decode");
1178+
if (decodeCarrierAC84(results, offset)) return true;
1179+
#endif // DECODE_CARRIER_AC84
11761180
// Typically new protocols are added above this line.
11771181
}
11781182
#if DECODE_HASH

src/IRrecv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,12 @@ class IRrecv {
583583
const uint16_t nbits = kCarrierAc40Bits,
584584
const bool strict = true);
585585
#endif // DECODE_CARRIER_AC40
586+
#if DECODE_CARRIER_AC84
587+
bool decodeCarrierAC84(decode_results *results,
588+
uint16_t offset = kStartOffset,
589+
const uint16_t nbits = kCarrierAc84Bits,
590+
const bool strict = true);
591+
#endif // DECODE_CARRIER_AC84
586592
#if DECODE_CARRIER_AC64
587593
bool decodeCarrierAC64(decode_results *results,
588594
uint16_t offset = kStartOffset,

src/IRremoteESP8266.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,13 @@
938938
#define SEND_WOWWEE _IR_ENABLE_DEFAULT_
939939
#endif // SEND_WOWWEE
940940

941+
#ifndef DECODE_CARRIER_AC84
942+
#define DECODE_CARRIER_AC84 _IR_ENABLE_DEFAULT_
943+
#endif // DECODE_CARRIER_AC84
944+
#ifndef SEND_CARRIER_AC84
945+
#define SEND_CARRIER_AC84 _IR_ENABLE_DEFAULT_
946+
#endif // SEND_CARRIER_AC84
947+
941948
#if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \
942949
DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \
943950
DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \
@@ -956,6 +963,7 @@
956963
DECODE_KELON168 || DECODE_HITACHI_AC296 || DECODE_CARRIER_AC128 || \
957964
DECODE_DAIKIN200 || DECODE_HAIER_AC160 || DECODE_TCL96AC || \
958965
DECODE_BOSCH144 || DECODE_SANYO_AC152 || DECODE_DAIKIN312 || \
966+
DECODE_CARRIER_AC84 || \
959967
false)
960968
// Add any DECODE to the above if it uses result->state (see kStateSizeMax)
961969
// you might also want to add the protocol to hasACState function
@@ -1120,8 +1128,9 @@ enum decode_type_t {
11201128
DAIKIN312,
11211129
GORENJE,
11221130
WOWWEE,
1131+
CARRIER_AC84, // 125
11231132
// Add new entries before this one, and update it to point to the last entry.
1124-
kLastDecodeType = WOWWEE,
1133+
kLastDecodeType = CARRIER_AC84,
11251134
};
11261135

11271136
// Message lengths & required repeat values
@@ -1159,6 +1168,9 @@ const uint16_t kCarrierAc40Bits = 40;
11591168
const uint16_t kCarrierAc40MinRepeat = 2;
11601169
const uint16_t kCarrierAc64Bits = 64;
11611170
const uint16_t kCarrierAc64MinRepeat = kNoRepeat;
1171+
const uint16_t kCarrierAc84StateLength = 11;
1172+
const uint16_t kCarrierAc84Bits = kCarrierAc84StateLength * 8 - 4;
1173+
const uint16_t kCarrierAc84MinRepeat = kNoRepeat;
11621174
const uint16_t kCarrierAc128StateLength = 16;
11631175
const uint16_t kCarrierAc128Bits = kCarrierAc128StateLength * 8;
11641176
const uint16_t kCarrierAc128MinRepeat = kNoRepeat;

src/IRsend.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
693693
return kBosch144Bits;
694694
case CORONA_AC:
695695
return kCoronaAcBits;
696+
case CARRIER_AC84:
697+
return kCarrierAc84Bits;
696698
case CARRIER_AC128:
697699
return kCarrierAc128Bits;
698700
case DAIKIN:
@@ -1172,6 +1174,11 @@ bool IRsend::send(const decode_type_t type, const uint8_t *state,
11721174
sendBosch144(state, nbytes);
11731175
break;
11741176
#endif // SEND_BOSCH144
1177+
#if SEND_CARRIER_AC84
1178+
case CARRIER_AC84:
1179+
sendCarrierAC84(state, nbytes);
1180+
break;
1181+
#endif // SEND_CARRIER_AC84
11751182
#if SEND_CARRIER_AC128
11761183
case CARRIER_AC128:
11771184
sendCarrierAC128(state, nbytes);

src/IRsend.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,11 @@ class IRsend {
608608
void sendCarrierAC64(uint64_t data, uint16_t nbits = kCarrierAc64Bits,
609609
uint16_t repeat = kCarrierAc64MinRepeat);
610610
#endif
611+
#if SEND_CARRIER_AC84
612+
void sendCarrierAC84(const uint8_t data[],
613+
const uint16_t nbytes = kCarrierAc84StateLength,
614+
const uint16_t repeat = kNoRepeat);
615+
#endif // SEND_CARRIER_AC84
611616
#if SEND_CARRIER_AC128
612617
void sendCarrierAC128(const uint8_t data[],
613618
uint16_t nbytes = kCarrierAc128StateLength,

src/IRtext.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,8 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
551551
D_STR_GORENJE, D_STR_UNSUPPORTED) "\x0"
552552
COND(DECODE_WOWWEE || SEND_WOWWEE,
553553
D_STR_WOWWEE, D_STR_UNSUPPORTED) "\x0"
554+
COND(DECODE_CARRIER_AC84 || SEND_CARRIER_AC84,
555+
D_STR_CARRIER_AC84, D_STR_UNSUPPORTED) "\x0"
554556
///< New protocol (macro) strings should be added just above this line.
555557
"\x0" ///< This string requires double null termination.
556558
};

src/IRutils.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#endif
77

88
#define __STDC_LIMIT_MACROS
9+
#include <math.h>
910
#include <stdint.h>
1011
#include <string.h>
1112
#include <algorithm>
@@ -173,6 +174,7 @@ bool hasACState(const decode_type_t protocol) {
173174
case AMCOR:
174175
case ARGO:
175176
case BOSCH144:
177+
case CARRIER_AC84:
176178
case CARRIER_AC128:
177179
case CORONA_AC:
178180
case DAIKIN:
@@ -304,7 +306,7 @@ String resultToSourceCode(const decode_results * const results) {
304306
if (results->decode_type != UNKNOWN) {
305307
if (hasState) {
306308
#if DECODE_AC
307-
uint16_t nbytes = results->bits / 8;
309+
uint16_t nbytes = ceil(static_cast<float>(results->bits) / 8.0);
308310
output += F("uint8_t state[");
309311
output += uint64ToString(nbytes);
310312
output += F("] = {");

src/ir_Carrier.cpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ const uint16_t kCarrierAc64OneSpace = 1736;
4646
const uint16_t kCarrierAc64ZeroSpace = 615;
4747
const uint32_t kCarrierAc64Gap = kDefaultMessageGap; // A guess.
4848

49+
//< @see: https://github.com/crankyoldgit/IRremoteESP8266/issues/1943#issue-1519570772
50+
const uint16_t kCarrierAc84HdrMark = 5850;
51+
const uint16_t kCarrierAc84Zero = 1175;
52+
const uint16_t kCarrierAc84One = 430;
53+
const uint16_t kCarrierAc84HdrSpace = kCarrierAc84Zero;
54+
const uint32_t kCarrierAc84Gap = kDefaultMessageGap; // A guess.
55+
const uint8_t kCarrierAc84ExtraBits = 4;
56+
const uint8_t kCarrierAc84ExtraTolerance = 5;
57+
4958
const uint16_t kCarrierAc128HdrMark = 4600;
5059
const uint16_t kCarrierAc128HdrSpace = 2600;
5160
const uint16_t kCarrierAc128Hdr2Mark = 9300;
@@ -645,3 +654,94 @@ bool IRrecv::decodeCarrierAC128(decode_results *results, uint16_t offset,
645654
return true;
646655
}
647656
#endif // DECODE_CARRIER_AC128
657+
658+
#if SEND_CARRIER_AC84
659+
/// Send a Carroer A/C 84 Bit formatted message.
660+
/// Status: BETA / Untested but probably works.
661+
/// @param[in] data The message to be sent.
662+
/// @param[in] nbytes The byte size of the message being sent.
663+
/// @param[in] repeat The number of times the command is to be repeated.
664+
void IRsend::sendCarrierAC84(const uint8_t data[], const uint16_t nbytes,
665+
const uint16_t repeat) {
666+
// Protocol uses a constant bit time encoding.
667+
for (uint16_t r = 0; r <= repeat; r++) {
668+
if (nbytes) {
669+
// The least significant `kCarrierAc84ExtraBits` bits of the first byte
670+
sendGeneric(kCarrierAc84HdrMark, kCarrierAc84HdrSpace, // Header
671+
kCarrierAc84Zero, kCarrierAc84One, // Data
672+
kCarrierAc84One, kCarrierAc84Zero,
673+
0, 0, // No footer
674+
GETBITS64(data[0], 0, kCarrierAc84ExtraBits),
675+
kCarrierAc84ExtraBits,
676+
38000, false, 0, 33);
677+
// The rest of the data.
678+
sendGeneric(0, 0, // No Header
679+
kCarrierAc84Zero, kCarrierAc84One, // Data
680+
kCarrierAc84One, kCarrierAc84Zero,
681+
kCarrierAc84Zero, kDefaultMessageGap, // Footer
682+
data + 1, nbytes - 1, 38000, false, 0, 33);
683+
}
684+
}
685+
}
686+
#endif // SEND_CARRIER_AC84
687+
688+
#if DECODE_CARRIER_AC84
689+
/// Decode the supplied Carroer A/C 84 Bit formatted message.
690+
/// Status: STABLE / Confirmed Working.
691+
/// @param[in,out] results Ptr to the data to decode & where to store the decode
692+
/// result.
693+
/// @param[in] offset The starting index to use when attempting to decode the
694+
/// raw data. Typically/Defaults to kStartOffset.
695+
/// @param[in] nbits The number of data bits to expect.
696+
/// @param[in] strict Flag indicating if we should perform strict matching.
697+
/// @return A boolean. True if it can decode it, false if it can't.
698+
bool IRrecv::decodeCarrierAC84(decode_results *results, uint16_t offset,
699+
const uint16_t nbits, const bool strict) {
700+
// Check if we have enough data to even possibly match.
701+
if (results->rawlen < 2 * nbits + kHeader + kFooter - 1 + offset)
702+
return false; // Can't possibly be a valid Carrier message.
703+
// Compliance check.
704+
if (strict && nbits != kCarrierAc84Bits) return false;
705+
706+
// This decoder expects to decode an unusual number of bits. Check before we
707+
// start.
708+
if (nbits % 8 != kCarrierAc84ExtraBits) return false;
709+
710+
uint64_t data = 0;
711+
uint16_t used = 0;
712+
713+
// Header + Data (kCarrierAc84ExtraBits only)
714+
used = matchGenericConstBitTime(results->rawbuf + offset, &data,
715+
results->rawlen - offset,
716+
kCarrierAc84ExtraBits,
717+
// Header (None)
718+
kCarrierAc84HdrMark, kCarrierAc84HdrSpace,
719+
// Data
720+
kCarrierAc84Zero, kCarrierAc84One,
721+
// No Footer
722+
0, 0,
723+
false,
724+
_tolerance + kCarrierAc84ExtraTolerance,
725+
kMarkExcess, false);
726+
if (!used) return false;
727+
// Stuff the captured data so far into the first byte of the state.
728+
*results->state = data;
729+
offset += used;
730+
// Capture the rest of the data as normal as we should be on a byte boundary.
731+
// Data + Footer
732+
if (!matchGeneric(results->rawbuf + offset, results->state + 1,
733+
results->rawlen - offset, nbits - kCarrierAc84ExtraBits,
734+
0, 0, // No Header expected.
735+
kCarrierAc84Zero, kCarrierAc84One, // Data
736+
kCarrierAc84One, kCarrierAc84Zero,
737+
kCarrierAc84Zero, kDefaultMessageGap, true,
738+
_tolerance + kCarrierAc84ExtraTolerance,
739+
kMarkExcess, false)) return false;
740+
741+
// Success
742+
results->decode_type = decode_type_t::CARRIER_AC84;
743+
results->bits = nbits;
744+
results->repeat = false;
745+
return true;
746+
}
747+
#endif // DECODE_CARRIER_AC84

src/ir_Carrier.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1127
55
/// @see https://docs.google.com/spreadsheets/d/1EZy78L0cn1KDIX1aKq2biptejFqCjD5HO3tLiRvXf48/edit#gid=0
66
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1797
7+
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1943
78

89
// Supports:
910
// Brand: Carrier/Surrey, Model: 42QG5A55970 remote
@@ -13,6 +14,8 @@
1314
// Brand: Carrier/Surrey, Model: 619EGX0220E0 A/C
1415
// Brand: Carrier/Surrey, Model: 53NGK009/012 Inverter
1516
// Brand: Carrier, Model: 40GKX0E2006 remote (CARRIER_AC128)
17+
// Brand: Carrier, Model: 3021203 RR03-S-Remote (CARRIER_AC84)
18+
// Brand: Carrier, Model: 342WM100CT A/C (CARRIER_AC84)
1619

1720
#ifndef IR_CARRIER_H_
1821
#define IR_CARRIER_H_

src/locale/defaults.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,9 @@ D_STR_INDIRECT " " D_STR_MODE
769769
#ifndef D_STR_CARRIER_AC64
770770
#define D_STR_CARRIER_AC64 D_STR_CARRIER_AC "64"
771771
#endif // D_STR_CARRIER_AC64
772+
#ifndef D_STR_CARRIER_AC84
773+
#define D_STR_CARRIER_AC84 D_STR_CARRIER_AC "84"
774+
#endif // D_STR_CARRIER_AC84
772775
#ifndef D_STR_CARRIER_AC128
773776
#define D_STR_CARRIER_AC128 D_STR_CARRIER_AC "128"
774777
#endif // D_STR_CARRIER_AC128

0 commit comments

Comments
 (0)