Skip to content

Commit

Permalink
Add support the WowWee 11-Bit RoboRaptor-X protocol.
Browse files Browse the repository at this point in the history
* Basic `sendWowwee()` & decodeWowwee()` routines.
* Unit test coverage including decoding of two different captured messages from a real remote.

Fixes #1938
  • Loading branch information
crankyoldgit committed Dec 30, 2022
1 parent 3a81664 commit bcbd326
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
DPRINTLN("Attempting GORENJE decode");
if (decodeGorenje(results, offset)) return true;
#endif // DECODE_GORENJE
#if DECODE_WOWWEE
DPRINTLN("Attempting WOWWEE decode");
if (decodeWowwee(results, offset)) return true;
#endif // DECODE_WOWWEE
// 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 @@ -865,6 +865,12 @@ class IRrecv {
const uint16_t nbits = kBosch144Bits,
const bool strict = true);
#endif // DECODE_BOSCH144
#if DECODE_WOWWEE
bool decodeWowwee(decode_results *results,
uint16_t offset = kStartOffset,
const uint16_t nbits = kWowweeBits,
const bool strict = true);
#endif // DECODE_WOWWEE
};

#endif // IRRECV_H_
12 changes: 11 additions & 1 deletion src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,13 @@
#define SEND_GORENJE _IR_ENABLE_DEFAULT_
#endif // SEND_GORENJE

#ifndef DECODE_WOWWEE
#define DECODE_WOWWEE _IR_ENABLE_DEFAULT_
#endif // DECODE_WOWWEE
#ifndef SEND_WOWWEE
#define SEND_WOWWEE _IR_ENABLE_DEFAULT_
#endif // SEND_WOWWEE

#if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \
DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \
DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \
Expand Down Expand Up @@ -1112,8 +1119,9 @@ enum decode_type_t {
SANYO_AC152,
DAIKIN312,
GORENJE,
WOWWEE,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = GORENJE,
kLastDecodeType = WOWWEE,
};

// Message lengths & required repeat values
Expand Down Expand Up @@ -1387,6 +1395,8 @@ const uint16_t kWhirlpoolAcStateLength = 21;
const uint16_t kWhirlpoolAcBits = kWhirlpoolAcStateLength * 8;
const uint16_t kWhirlpoolAcDefaultRepeat = kNoRepeat;
const uint16_t kWhynterBits = 32;
const uint16_t kWowweeBits = 11;
const uint16_t kWowweeDefaultRepeat = kNoRepeat;
const uint8_t kVestelAcBits = 56;
const uint16_t kXmpBits = 64;
const uint16_t kZepealBits = 16;
Expand Down
7 changes: 7 additions & 0 deletions src/IRsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
case MULTIBRACKETS:
case GORENJE:
return 8;
case WOWWEE:
return 11;
case RC5:
case SYMPHONY:
return 12;
Expand Down Expand Up @@ -1120,6 +1122,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
sendWhynter(data, nbits, min_repeat);
break;
#endif
#if SEND_WOWWEE
case WOWWEE:
sendWowwee(data, nbits, min_repeat);
break;
#endif // SEND_WOWWEE
#if SEND_XMP
case XMP:
sendXmp(data, nbits, min_repeat);
Expand Down
4 changes: 4 additions & 0 deletions src/IRsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,10 @@ class IRsend {
const uint16_t nbytes = kBosch144StateLength,
const uint16_t repeat = kNoRepeat);
#endif // SEND_BOSCH144
#if SEND_WOWWEE
void sendWowwee(const uint64_t data, const uint16_t nbits = kWowweeBits,
const uint16_t repeat = kWowweeDefaultRepeat);
#endif // SEND_WOWWEE

protected:
#ifdef UNIT_TEST
Expand Down
2 changes: 2 additions & 0 deletions src/IRtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,8 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
D_STR_DAIKIN312, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_GORENJE || SEND_GORENJE,
D_STR_GORENJE, D_STR_UNSUPPORTED) "\x0"
COND(DECODE_WOWWEE || SEND_WOWWEE,
D_STR_WOWWEE, D_STR_UNSUPPORTED) "\x0"
///< New protocol (macro) strings should be added just above this line.
"\x0" ///< This string requires double null termination.
};
Expand Down
69 changes: 69 additions & 0 deletions src/ir_Wowwee.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2022 David Conran

/// @file
/// @brief Support for WowWee RoboRapter protocol
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues1938

// Supports:
// Brand: WowWee, Model: RoboRapter-X

#include <algorithm>
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"

// Constants
const uint16_t kWowweeHdrMark = 6684;
const uint16_t kWowweeHdrSpace = 723;
const uint16_t kWowweeBitMark = 912;
const uint16_t kWowweeOneSpace = 3259;
const uint16_t kWowweeZeroSpace = kWowweeHdrSpace;
const uint16_t kWowweeFreq = 38000; // Hz. (Just a guess)


#if SEND_WOWWEE
/// Send a WowWee formatted message.
/// Status: BETA / Untested on a real device.
/// @param[in] data The message to be sent.
/// @param[in] nbits The number of bits of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
void IRsend::sendWowwee(uint64_t data, uint16_t nbits, uint16_t repeat) {
sendGeneric(kWowweeHdrMark, kWowweeHdrSpace,
kWowweeBitMark, kWowweeOneSpace,
kWowweeBitMark, kWowweeZeroSpace,
kWowweeBitMark, kDefaultMessageGap, data,
nbits, kWowweeFreq, true, repeat, 33);
}
#endif // SEND_WOWWEE

#if DECODE_WOWWEE
/// Decode the supplied WowWee message.
/// Status: BETA / Untested on a real device.
/// @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.
/// @param[in] strict Flag indicating if we should perform strict matching.
bool IRrecv::decodeWowwee(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (strict && nbits != kWowweeBits)
return false; // We expect Wowwee to be a certain sized message.

uint64_t data = 0;

// Match Header + Data + Footer
if (!matchGeneric(results->rawbuf + offset, &data,
results->rawlen - offset, nbits,
kWowweeHdrMark, kWowweeHdrSpace,
kWowweeBitMark, kWowweeOneSpace,
kWowweeBitMark, kWowweeZeroSpace,
kWowweeBitMark, kDefaultMessageGap, true)) return false;
// Success
results->bits = nbits;
results->value = data;
results->decode_type = WOWWEE;
results->command = 0;
results->address = 0;
return true;
}
#endif // DECODE_WOWWEE
3 changes: 3 additions & 0 deletions src/locale/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,9 @@ D_STR_INDIRECT " " D_STR_MODE
#ifndef D_STR_WHYNTER
#define D_STR_WHYNTER "WHYNTER"
#endif // D_STR_WHYNTER
#ifndef D_STR_WOWWEE
#define D_STR_WOWWEE "WOWWEE"
#endif // D_STR_WOWWEE
#ifndef D_STR_XMP
#define D_STR_XMP "XMP"
#endif // D_STR_XMP
Expand Down
103 changes: 103 additions & 0 deletions test/ir_Wowwee_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2022 David Conran

#include "IRac.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"

TEST(TestUtils, Housekeeping) {
ASSERT_EQ("WOWWEE", typeToString(decode_type_t::WOWWEE));
ASSERT_EQ(decode_type_t::WOWWEE, strToDecodeType("WOWWEE"));
ASSERT_FALSE(hasACState(decode_type_t::WOWWEE));
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::WOWWEE));
ASSERT_EQ(kWowweeBits, IRsend::defaultBits(decode_type_t::WOWWEE));
ASSERT_EQ(kWowweeDefaultRepeat, IRsend::minRepeats(decode_type_t::WOWWEE));
}

// Tests for sendWowwee().
// Test sending typical data only.
TEST(TestSendWowwee, SendDataOnly) {
IRsendTest irsend(kGpioUnused);
irsend.begin();

irsend.reset();
irsend.sendWowwee(0x186); // Nikai TV Power Off.
EXPECT_EQ(
"f38000d33"
"m6684s723"
"m912s723m912s723m912s3259m912s3259m912s723m912s723m912s723m912s723"
"m912s3259m912s3259m912s723m912s100000",
irsend.outputStr());

irsend.reset();
}

// Tests for decodeWowwee().

// Decode normal Wowwee messages.
TEST(TestDecodeWowwee, RealDecode) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1938#issue-1513240242
const uint16_t rawForward[25] = {
6684, 740, 918, 724, 942, 724, 918, 3250, 870, 3268, 872, 770, 940, 690,
942, 688, 942, 738, 942, 3250, 868, 3268, 872, 732, 918
}; // UNKNOWN 7469BF81
irsend.reset();
irsend.sendRaw(rawForward, 25, 38);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
EXPECT_EQ(0x186, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.command);
EXPECT_EQ(0x0, irsend.capture.address);

// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1938#issue-1513240242
const uint16_t rawLeft[25] = {
6630, 764, 868, 762, 892, 788, 866, 3324, 792, 3348, 818, 760, 866, 788,
894, 772, 892, 750, 870, 786, 920, 750, 864, 776, 868
}; // UNKNOWN 28A1120F
irsend.reset();
irsend.sendRaw(rawLeft, 25, 38);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
EXPECT_EQ(0x180, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.command);
EXPECT_EQ(0x0, irsend.capture.address);
}

// Decode normal repeated Wowwee messages.
TEST(TestDecodeWowwee, SyntheticDecode) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
irsend.begin();

// Normal Wowwee 11-bit message.
irsend.reset();
irsend.sendWowwee(0x186);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
EXPECT_EQ(0x186, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.command);
EXPECT_EQ(0x0, irsend.capture.address);

// Normal Wowwee 11-bit message.
irsend.reset();
irsend.sendWowwee(0x180);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
EXPECT_EQ(0x180, irsend.capture.value);
EXPECT_EQ(0x0, irsend.capture.command);
EXPECT_EQ(0x0, irsend.capture.address);
}

0 comments on commit bcbd326

Please sign in to comment.