Skip to content

Commit fa77d78

Browse files
authored
Add support the WowWee 11-Bit RoboRaptor-X protocol. (#1939)
* Basic `sendWowwee()` & decodeWowwee()` routines. * Unit test coverage including decoding of two different captured messages from a real remote. * Add reference for available/known RoboRaptor-X codes. Fixes #1938
1 parent 3a81664 commit fa77d78

File tree

9 files changed

+231
-1
lines changed

9 files changed

+231
-1
lines changed

src/IRrecv.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
11691169
DPRINTLN("Attempting GORENJE decode");
11701170
if (decodeGorenje(results, offset)) return true;
11711171
#endif // DECODE_GORENJE
1172+
#if DECODE_WOWWEE
1173+
DPRINTLN("Attempting WOWWEE decode");
1174+
if (decodeWowwee(results, offset)) return true;
1175+
#endif // DECODE_WOWWEE
11721176
// Typically new protocols are added above this line.
11731177
}
11741178
#if DECODE_HASH

src/IRrecv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,12 @@ class IRrecv {
865865
const uint16_t nbits = kBosch144Bits,
866866
const bool strict = true);
867867
#endif // DECODE_BOSCH144
868+
#if DECODE_WOWWEE
869+
bool decodeWowwee(decode_results *results,
870+
uint16_t offset = kStartOffset,
871+
const uint16_t nbits = kWowweeBits,
872+
const bool strict = true);
873+
#endif // DECODE_WOWWEE
868874
};
869875

870876
#endif // IRRECV_H_

src/IRremoteESP8266.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,13 @@
931931
#define SEND_GORENJE _IR_ENABLE_DEFAULT_
932932
#endif // SEND_GORENJE
933933

934+
#ifndef DECODE_WOWWEE
935+
#define DECODE_WOWWEE _IR_ENABLE_DEFAULT_
936+
#endif // DECODE_WOWWEE
937+
#ifndef SEND_WOWWEE
938+
#define SEND_WOWWEE _IR_ENABLE_DEFAULT_
939+
#endif // SEND_WOWWEE
940+
934941
#if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \
935942
DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \
936943
DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \
@@ -1112,8 +1119,9 @@ enum decode_type_t {
11121119
SANYO_AC152,
11131120
DAIKIN312,
11141121
GORENJE,
1122+
WOWWEE,
11151123
// Add new entries before this one, and update it to point to the last entry.
1116-
kLastDecodeType = GORENJE,
1124+
kLastDecodeType = WOWWEE,
11171125
};
11181126

11191127
// Message lengths & required repeat values
@@ -1387,6 +1395,8 @@ const uint16_t kWhirlpoolAcStateLength = 21;
13871395
const uint16_t kWhirlpoolAcBits = kWhirlpoolAcStateLength * 8;
13881396
const uint16_t kWhirlpoolAcDefaultRepeat = kNoRepeat;
13891397
const uint16_t kWhynterBits = 32;
1398+
const uint16_t kWowweeBits = 11;
1399+
const uint16_t kWowweeDefaultRepeat = kNoRepeat;
13901400
const uint8_t kVestelAcBits = 56;
13911401
const uint16_t kXmpBits = 64;
13921402
const uint16_t kZepealBits = 16;

src/IRsend.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
605605
case MULTIBRACKETS:
606606
case GORENJE:
607607
return 8;
608+
case WOWWEE:
609+
return 11;
608610
case RC5:
609611
case SYMPHONY:
610612
return 12;
@@ -1120,6 +1122,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
11201122
sendWhynter(data, nbits, min_repeat);
11211123
break;
11221124
#endif
1125+
#if SEND_WOWWEE
1126+
case WOWWEE:
1127+
sendWowwee(data, nbits, min_repeat);
1128+
break;
1129+
#endif // SEND_WOWWEE
11231130
#if SEND_XMP
11241131
case XMP:
11251132
sendXmp(data, nbits, min_repeat);

src/IRsend.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,10 @@ class IRsend {
870870
const uint16_t nbytes = kBosch144StateLength,
871871
const uint16_t repeat = kNoRepeat);
872872
#endif // SEND_BOSCH144
873+
#if SEND_WOWWEE
874+
void sendWowwee(const uint64_t data, const uint16_t nbits = kWowweeBits,
875+
const uint16_t repeat = kWowweeDefaultRepeat);
876+
#endif // SEND_WOWWEE
873877

874878
protected:
875879
#ifdef UNIT_TEST

src/IRtext.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,8 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
549549
D_STR_DAIKIN312, D_STR_UNSUPPORTED) "\x0"
550550
COND(DECODE_GORENJE || SEND_GORENJE,
551551
D_STR_GORENJE, D_STR_UNSUPPORTED) "\x0"
552+
COND(DECODE_WOWWEE || SEND_WOWWEE,
553+
D_STR_WOWWEE, D_STR_UNSUPPORTED) "\x0"
552554
///< New protocol (macro) strings should be added just above this line.
553555
"\x0" ///< This string requires double null termination.
554556
};

src/ir_Wowwee.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright 2022 David Conran
2+
3+
/// @file
4+
/// @brief Support for WowWee RoboRapter protocol
5+
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues1938
6+
7+
// Supports:
8+
// Brand: WowWee, Model: RoboRapter-X
9+
10+
// WowWee RoboRapter-X messages
11+
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1938#issuecomment-1367968228
12+
//
13+
// Button Code
14+
// ====== =====
15+
// Left 0x180
16+
// Forward 0x186
17+
// Backward 0x187
18+
// Right 0x188
19+
// Stop 0x18E
20+
// Head Counterclockwise 0x191
21+
// Tail Left 0x192
22+
// Tail Right 0x193
23+
// Head Clockwise 0x194
24+
// Guard Mode 0x1B0
25+
// Roam 0x1B1
26+
// Cautious Mood 0x1B2
27+
// Playful Mood 0x1B3
28+
// Hunting Mood 0x1B4
29+
// Demo 0x1D0
30+
// Bite 0x1D1
31+
32+
#include <algorithm>
33+
#include "IRrecv.h"
34+
#include "IRsend.h"
35+
#include "IRutils.h"
36+
37+
// Constants
38+
const uint16_t kWowweeHdrMark = 6684;
39+
const uint16_t kWowweeHdrSpace = 723;
40+
const uint16_t kWowweeBitMark = 912;
41+
const uint16_t kWowweeOneSpace = 3259;
42+
const uint16_t kWowweeZeroSpace = kWowweeHdrSpace;
43+
const uint16_t kWowweeFreq = 38000; // Hz. (Just a guess)
44+
45+
46+
#if SEND_WOWWEE
47+
/// Send a WowWee formatted message.
48+
/// Status: STABLE / Confirmed working with real device.
49+
/// @param[in] data The message to be sent.
50+
/// @param[in] nbits The number of bits of message to be sent.
51+
/// @param[in] repeat The number of times the command is to be repeated.
52+
void IRsend::sendWowwee(uint64_t data, uint16_t nbits, uint16_t repeat) {
53+
sendGeneric(kWowweeHdrMark, kWowweeHdrSpace,
54+
kWowweeBitMark, kWowweeOneSpace,
55+
kWowweeBitMark, kWowweeZeroSpace,
56+
kWowweeBitMark, kDefaultMessageGap, data,
57+
nbits, kWowweeFreq, true, repeat, 33);
58+
}
59+
#endif // SEND_WOWWEE
60+
61+
#if DECODE_WOWWEE
62+
/// Decode the supplied WowWee message.
63+
/// Status: STABLE / Confirmed working with real device.
64+
/// @param[in,out] results Ptr to the data to decode & where to store the result
65+
/// @param[in] offset The starting index to use when attempting to decode the
66+
/// raw data. Typically/Defaults to kStartOffset.
67+
/// @param[in] nbits The number of data bits to expect.
68+
/// @param[in] strict Flag indicating if we should perform strict matching.
69+
bool IRrecv::decodeWowwee(decode_results *results, uint16_t offset,
70+
const uint16_t nbits, const bool strict) {
71+
if (strict && nbits != kWowweeBits)
72+
return false; // We expect Wowwee to be a certain sized message.
73+
74+
uint64_t data = 0;
75+
76+
// Match Header + Data + Footer
77+
if (!matchGeneric(results->rawbuf + offset, &data,
78+
results->rawlen - offset, nbits,
79+
kWowweeHdrMark, kWowweeHdrSpace,
80+
kWowweeBitMark, kWowweeOneSpace,
81+
kWowweeBitMark, kWowweeZeroSpace,
82+
kWowweeBitMark, kDefaultMessageGap, true)) return false;
83+
// Success
84+
results->bits = nbits;
85+
results->value = data;
86+
results->decode_type = WOWWEE;
87+
results->command = 0;
88+
results->address = 0;
89+
return true;
90+
}
91+
#endif // DECODE_WOWWEE

src/locale/defaults.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,9 @@ D_STR_INDIRECT " " D_STR_MODE
11051105
#ifndef D_STR_WHYNTER
11061106
#define D_STR_WHYNTER "WHYNTER"
11071107
#endif // D_STR_WHYNTER
1108+
#ifndef D_STR_WOWWEE
1109+
#define D_STR_WOWWEE "WOWWEE"
1110+
#endif // D_STR_WOWWEE
11081111
#ifndef D_STR_XMP
11091112
#define D_STR_XMP "XMP"
11101113
#endif // D_STR_XMP

test/ir_Wowwee_test.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright 2022 David Conran
2+
3+
#include "IRac.h"
4+
#include "IRrecv.h"
5+
#include "IRrecv_test.h"
6+
#include "IRsend.h"
7+
#include "IRsend_test.h"
8+
#include "gtest/gtest.h"
9+
10+
TEST(TestUtils, Housekeeping) {
11+
ASSERT_EQ("WOWWEE", typeToString(decode_type_t::WOWWEE));
12+
ASSERT_EQ(decode_type_t::WOWWEE, strToDecodeType("WOWWEE"));
13+
ASSERT_FALSE(hasACState(decode_type_t::WOWWEE));
14+
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::WOWWEE));
15+
ASSERT_EQ(kWowweeBits, IRsend::defaultBits(decode_type_t::WOWWEE));
16+
ASSERT_EQ(kWowweeDefaultRepeat, IRsend::minRepeats(decode_type_t::WOWWEE));
17+
}
18+
19+
// Tests for sendWowwee().
20+
// Test sending typical data only.
21+
TEST(TestSendWowwee, SendDataOnly) {
22+
IRsendTest irsend(kGpioUnused);
23+
irsend.begin();
24+
25+
irsend.reset();
26+
irsend.sendWowwee(0x186); // Nikai TV Power Off.
27+
EXPECT_EQ(
28+
"f38000d33"
29+
"m6684s723"
30+
"m912s723m912s723m912s3259m912s3259m912s723m912s723m912s723m912s723"
31+
"m912s3259m912s3259m912s723m912s100000",
32+
irsend.outputStr());
33+
34+
irsend.reset();
35+
}
36+
37+
// Tests for decodeWowwee().
38+
39+
// Decode normal Wowwee messages.
40+
TEST(TestDecodeWowwee, RealDecode) {
41+
IRsendTest irsend(kGpioUnused);
42+
IRrecv irrecv(kGpioUnused);
43+
irsend.begin();
44+
45+
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1938#issue-1513240242
46+
const uint16_t rawForward[25] = {
47+
6684, 740, 918, 724, 942, 724, 918, 3250, 870, 3268, 872, 770, 940, 690,
48+
942, 688, 942, 738, 942, 3250, 868, 3268, 872, 732, 918
49+
}; // UNKNOWN 7469BF81
50+
irsend.reset();
51+
irsend.sendRaw(rawForward, 25, 38);
52+
irsend.makeDecodeResult();
53+
ASSERT_TRUE(irrecv.decode(&irsend.capture));
54+
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
55+
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
56+
EXPECT_EQ(0x186, irsend.capture.value);
57+
EXPECT_EQ(0x0, irsend.capture.command);
58+
EXPECT_EQ(0x0, irsend.capture.address);
59+
60+
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1938#issue-1513240242
61+
const uint16_t rawLeft[25] = {
62+
6630, 764, 868, 762, 892, 788, 866, 3324, 792, 3348, 818, 760, 866, 788,
63+
894, 772, 892, 750, 870, 786, 920, 750, 864, 776, 868
64+
}; // UNKNOWN 28A1120F
65+
irsend.reset();
66+
irsend.sendRaw(rawLeft, 25, 38);
67+
irsend.makeDecodeResult();
68+
ASSERT_TRUE(irrecv.decode(&irsend.capture));
69+
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
70+
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
71+
EXPECT_EQ(0x180, irsend.capture.value);
72+
EXPECT_EQ(0x0, irsend.capture.command);
73+
EXPECT_EQ(0x0, irsend.capture.address);
74+
}
75+
76+
// Decode normal repeated Wowwee messages.
77+
TEST(TestDecodeWowwee, SyntheticDecode) {
78+
IRsendTest irsend(kGpioUnused);
79+
IRrecv irrecv(kGpioUnused);
80+
irsend.begin();
81+
82+
// Normal Wowwee 11-bit message.
83+
irsend.reset();
84+
irsend.sendWowwee(0x186);
85+
irsend.makeDecodeResult();
86+
ASSERT_TRUE(irrecv.decode(&irsend.capture));
87+
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
88+
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
89+
EXPECT_EQ(0x186, irsend.capture.value);
90+
EXPECT_EQ(0x0, irsend.capture.command);
91+
EXPECT_EQ(0x0, irsend.capture.address);
92+
93+
// Normal Wowwee 11-bit message.
94+
irsend.reset();
95+
irsend.sendWowwee(0x180);
96+
irsend.makeDecodeResult();
97+
ASSERT_TRUE(irrecv.decode(&irsend.capture));
98+
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
99+
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
100+
EXPECT_EQ(0x180, irsend.capture.value);
101+
EXPECT_EQ(0x0, irsend.capture.command);
102+
EXPECT_EQ(0x0, irsend.capture.address);
103+
}

0 commit comments

Comments
 (0)